Completed
Pull Request — master (#6836)
by René
12:46
created
apps/files_external/lib/Lib/Notify/SMBNotifyHandler.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -102,7 +102,7 @@
 block discarded – undo
102 102
 
103 103
 	/**
104 104
 	 * @param \Icewind\SMB\Change $change
105
-	 * @return IChange|null
105
+	 * @return null|Change
106 106
 	 */
107 107
 	private function mapChange(\Icewind\SMB\Change $change) {
108 108
 		$path = $this->relativePath($change->getPath());
Please login to merge, or discard this patch.
Indentation   +109 added lines, -109 removed lines patch added patch discarded remove patch
@@ -29,122 +29,122 @@
 block discarded – undo
29 29
 use OCP\Files\Notify\INotifyHandler;
30 30
 
31 31
 class SMBNotifyHandler implements INotifyHandler {
32
-	/**
33
-	 * @var \Icewind\SMB\INotifyHandler
34
-	 */
35
-	private $shareNotifyHandler;
32
+    /**
33
+     * @var \Icewind\SMB\INotifyHandler
34
+     */
35
+    private $shareNotifyHandler;
36 36
 
37
-	/**
38
-	 * @var string
39
-	 */
40
-	private $root;
37
+    /**
38
+     * @var string
39
+     */
40
+    private $root;
41 41
 
42
-	private $oldRenamePath = null;
42
+    private $oldRenamePath = null;
43 43
 
44
-	/**
45
-	 * SMBNotifyHandler constructor.
46
-	 *
47
-	 * @param \Icewind\SMB\INotifyHandler $shareNotifyHandler
48
-	 * @param string $root
49
-	 */
50
-	public function __construct(\Icewind\SMB\INotifyHandler $shareNotifyHandler, $root) {
51
-		$this->shareNotifyHandler = $shareNotifyHandler;
52
-		$this->root = $root;
53
-	}
44
+    /**
45
+     * SMBNotifyHandler constructor.
46
+     *
47
+     * @param \Icewind\SMB\INotifyHandler $shareNotifyHandler
48
+     * @param string $root
49
+     */
50
+    public function __construct(\Icewind\SMB\INotifyHandler $shareNotifyHandler, $root) {
51
+        $this->shareNotifyHandler = $shareNotifyHandler;
52
+        $this->root = $root;
53
+    }
54 54
 
55
-	private function relativePath($fullPath) {
56
-		if ($fullPath === $this->root) {
57
-			return '';
58
-		} else if (substr($fullPath, 0, strlen($this->root)) === $this->root) {
59
-			return substr($fullPath, strlen($this->root));
60
-		} else {
61
-			return null;
62
-		}
63
-	}
55
+    private function relativePath($fullPath) {
56
+        if ($fullPath === $this->root) {
57
+            return '';
58
+        } else if (substr($fullPath, 0, strlen($this->root)) === $this->root) {
59
+            return substr($fullPath, strlen($this->root));
60
+        } else {
61
+            return null;
62
+        }
63
+    }
64 64
 
65
-	public function listen(callable $callback) {
66
-		$oldRenamePath = null;
67
-		$this->shareNotifyHandler->listen(function (\Icewind\SMB\Change $shareChange) use ($callback) {
68
-			$change = $this->mapChange($shareChange);
69
-			if (!is_null($change)) {
70
-				return $callback($change);
71
-			} else {
72
-				return true;
73
-			}
74
-		});
75
-	}
65
+    public function listen(callable $callback) {
66
+        $oldRenamePath = null;
67
+        $this->shareNotifyHandler->listen(function (\Icewind\SMB\Change $shareChange) use ($callback) {
68
+            $change = $this->mapChange($shareChange);
69
+            if (!is_null($change)) {
70
+                return $callback($change);
71
+            } else {
72
+                return true;
73
+            }
74
+        });
75
+    }
76 76
 
77
-	/**
78
-	 * Get all changes detected since the start of the notify process or the last call to getChanges
79
-	 *
80
-	 * @return IChange[]
81
-	 */
82
-	public function getChanges() {
83
-		$shareChanges = $this->shareNotifyHandler->getChanges();
84
-		$changes = [];
85
-		foreach ($shareChanges as $shareChange) {
86
-			$change = $this->mapChange($shareChange);
87
-			if ($change) {
88
-				$changes[] = $change;
89
-			}
90
-		}
91
-		return $changes;
92
-	}
77
+    /**
78
+     * Get all changes detected since the start of the notify process or the last call to getChanges
79
+     *
80
+     * @return IChange[]
81
+     */
82
+    public function getChanges() {
83
+        $shareChanges = $this->shareNotifyHandler->getChanges();
84
+        $changes = [];
85
+        foreach ($shareChanges as $shareChange) {
86
+            $change = $this->mapChange($shareChange);
87
+            if ($change) {
88
+                $changes[] = $change;
89
+            }
90
+        }
91
+        return $changes;
92
+    }
93 93
 
94
-	/**
95
-	 * Stop listening for changes
96
-	 *
97
-	 * Note that any pending changes will be discarded
98
-	 */
99
-	public function stop() {
100
-		$this->shareNotifyHandler->stop();
101
-	}
94
+    /**
95
+     * Stop listening for changes
96
+     *
97
+     * Note that any pending changes will be discarded
98
+     */
99
+    public function stop() {
100
+        $this->shareNotifyHandler->stop();
101
+    }
102 102
 
103
-	/**
104
-	 * @param \Icewind\SMB\Change $change
105
-	 * @return IChange|null
106
-	 */
107
-	private function mapChange(\Icewind\SMB\Change $change) {
108
-		$path = $this->relativePath($change->getPath());
109
-		if (is_null($path)) {
110
-			return null;
111
-		}
112
-		if ($change->getCode() === \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_OLD) {
113
-			$this->oldRenamePath = $path;
114
-			return null;
115
-		}
116
-		$type = $this->mapNotifyType($change->getCode());
117
-		if (is_null($type)) {
118
-			return null;
119
-		}
120
-		if ($type === IChange::RENAMED) {
121
-			if (!is_null($this->oldRenamePath)) {
122
-				$result = new RenameChange($type, $this->oldRenamePath, $path);
123
-				$this->oldRenamePath = null;
124
-			} else {
125
-				$result = null;
126
-			}
127
-		} else {
128
-			$result = new Change($type, $path);
129
-		}
130
-		return $result;
131
-	}
103
+    /**
104
+     * @param \Icewind\SMB\Change $change
105
+     * @return IChange|null
106
+     */
107
+    private function mapChange(\Icewind\SMB\Change $change) {
108
+        $path = $this->relativePath($change->getPath());
109
+        if (is_null($path)) {
110
+            return null;
111
+        }
112
+        if ($change->getCode() === \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_OLD) {
113
+            $this->oldRenamePath = $path;
114
+            return null;
115
+        }
116
+        $type = $this->mapNotifyType($change->getCode());
117
+        if (is_null($type)) {
118
+            return null;
119
+        }
120
+        if ($type === IChange::RENAMED) {
121
+            if (!is_null($this->oldRenamePath)) {
122
+                $result = new RenameChange($type, $this->oldRenamePath, $path);
123
+                $this->oldRenamePath = null;
124
+            } else {
125
+                $result = null;
126
+            }
127
+        } else {
128
+            $result = new Change($type, $path);
129
+        }
130
+        return $result;
131
+    }
132 132
 
133
-	private function mapNotifyType($smbType) {
134
-		switch ($smbType) {
135
-			case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED:
136
-				return IChange::ADDED;
137
-			case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED:
138
-				return IChange::REMOVED;
139
-			case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED:
140
-			case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED_STREAM:
141
-			case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED_STREAM:
142
-			case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED_STREAM:
143
-				return IChange::MODIFIED;
144
-			case \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_NEW:
145
-				return IChange::RENAMED;
146
-			default:
147
-				return null;
148
-		}
149
-	}
133
+    private function mapNotifyType($smbType) {
134
+        switch ($smbType) {
135
+            case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED:
136
+                return IChange::ADDED;
137
+            case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED:
138
+                return IChange::REMOVED;
139
+            case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED:
140
+            case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED_STREAM:
141
+            case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED_STREAM:
142
+            case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED_STREAM:
143
+                return IChange::MODIFIED;
144
+            case \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_NEW:
145
+                return IChange::RENAMED;
146
+            default:
147
+                return null;
148
+        }
149
+    }
150 150
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -64,7 +64,7 @@
 block discarded – undo
64 64
 
65 65
 	public function listen(callable $callback) {
66 66
 		$oldRenamePath = null;
67
-		$this->shareNotifyHandler->listen(function (\Icewind\SMB\Change $shareChange) use ($callback) {
67
+		$this->shareNotifyHandler->listen(function(\Icewind\SMB\Change $shareChange) use ($callback) {
68 68
 			$change = $this->mapChange($shareChange);
69 69
 			if (!is_null($change)) {
70 70
 				return $callback($change);
Please login to merge, or discard this patch.
lib/private/legacy/app.php 3 patches
Doc Comments   +6 added lines, -1 removed lines patch added patch discarded remove patch
@@ -1063,7 +1063,7 @@  discard block
 block discarded – undo
1063 1063
 	 * @param string $app
1064 1064
 	 * @param \OCP\IConfig $config
1065 1065
 	 * @param \OCP\IL10N $l
1066
-	 * @return bool
1066
+	 * @return string
1067 1067
 	 *
1068 1068
 	 * @throws Exception if app is not compatible with this version of ownCloud
1069 1069
 	 * @throws Exception if no app-name was specified
@@ -1243,6 +1243,11 @@  discard block
 block discarded – undo
1243 1243
 		}
1244 1244
 	}
1245 1245
 
1246
+	/**
1247
+	 * @param string $lang
1248
+	 *
1249
+	 * @return string
1250
+	 */
1246 1251
 	protected static function findBestL10NOption($options, $lang) {
1247 1252
 		$fallback = $similarLangFallback = $englishFallback = false;
1248 1253
 
Please login to merge, or discard this patch.
Spacing   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -111,9 +111,9 @@  discard block
 block discarded – undo
111 111
 		$apps = self::getEnabledApps();
112 112
 
113 113
 		// Add each apps' folder as allowed class path
114
-		foreach($apps as $app) {
114
+		foreach ($apps as $app) {
115 115
 			$path = self::getAppPath($app);
116
-			if($path !== false) {
116
+			if ($path !== false) {
117 117
 				self::registerAutoloading($app, $path);
118 118
 			}
119 119
 		}
@@ -138,15 +138,15 @@  discard block
 block discarded – undo
138 138
 	public static function loadApp($app) {
139 139
 		self::$loadedApps[] = $app;
140 140
 		$appPath = self::getAppPath($app);
141
-		if($appPath === false) {
141
+		if ($appPath === false) {
142 142
 			return;
143 143
 		}
144 144
 
145 145
 		// in case someone calls loadApp() directly
146 146
 		self::registerAutoloading($app, $appPath);
147 147
 
148
-		if (is_file($appPath . '/appinfo/app.php')) {
149
-			\OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
148
+		if (is_file($appPath.'/appinfo/app.php')) {
149
+			\OC::$server->getEventLogger()->start('load_app_'.$app, 'Load app: '.$app);
150 150
 			self::requireAppFile($app);
151 151
 			if (self::isType($app, array('authentication'))) {
152 152
 				// since authentication apps affect the "is app enabled for group" check,
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
 				// enabled for groups
156 156
 				self::$enabledAppsCache = array();
157 157
 			}
158
-			\OC::$server->getEventLogger()->end('load_app_' . $app);
158
+			\OC::$server->getEventLogger()->end('load_app_'.$app);
159 159
 		}
160 160
 
161 161
 		$info = self::getAppInfo($app);
@@ -179,7 +179,7 @@  discard block
 block discarded – undo
179 179
 			$plugins = isset($info['collaboration']['plugins']['plugin']['@value']) ?
180 180
 				[$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin'];
181 181
 			foreach ($plugins as $plugin) {
182
-				if($plugin['@attributes']['type'] === 'collaborator-search') {
182
+				if ($plugin['@attributes']['type'] === 'collaborator-search') {
183 183
 					$pluginInfo = [
184 184
 						'shareType' => $plugin['@attributes']['share-type'],
185 185
 						'class' => $plugin['@value'],
@@ -196,17 +196,17 @@  discard block
 block discarded – undo
196 196
 	 * @param string $path
197 197
 	 */
198 198
 	public static function registerAutoloading($app, $path) {
199
-		$key = $app . '-' . $path;
200
-		if(isset(self::$alreadyRegistered[$key])) {
199
+		$key = $app.'-'.$path;
200
+		if (isset(self::$alreadyRegistered[$key])) {
201 201
 			return;
202 202
 		}
203 203
 		self::$alreadyRegistered[$key] = true;
204 204
 		// Register on PSR-4 composer autoloader
205 205
 		$appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
206 206
 		\OC::$server->registerNamespace($app, $appNamespace);
207
-		\OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
207
+		\OC::$composerAutoloader->addPsr4($appNamespace.'\\', $path.'/lib/', true);
208 208
 		if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
209
-			\OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);
209
+			\OC::$composerAutoloader->addPsr4($appNamespace.'\\Tests\\', $path.'/tests/', true);
210 210
 		}
211 211
 
212 212
 		// Register on legacy autoloader
@@ -221,7 +221,7 @@  discard block
 block discarded – undo
221 221
 	private static function requireAppFile($app) {
222 222
 		try {
223 223
 			// encapsulated here to avoid variable scope conflicts
224
-			require_once $app . '/appinfo/app.php';
224
+			require_once $app.'/appinfo/app.php';
225 225
 		} catch (Error $ex) {
226 226
 			\OC::$server->getLogger()->logException($ex);
227 227
 			$blacklist = \OC::$server->getAppManager()->getAlwaysEnabledApps();
@@ -275,7 +275,7 @@  discard block
 block discarded – undo
275 275
 	 */
276 276
 	public static function setAppTypes($app) {
277 277
 		$appData = self::getAppInfo($app);
278
-		if(!is_array($appData)) {
278
+		if (!is_array($appData)) {
279 279
 			return;
280 280
 		}
281 281
 
@@ -327,8 +327,8 @@  discard block
 block discarded – undo
327 327
 		} else {
328 328
 			$apps = $appManager->getEnabledAppsForUser($user);
329 329
 		}
330
-		$apps = array_filter($apps, function ($app) {
331
-			return $app !== 'files';//we add this manually
330
+		$apps = array_filter($apps, function($app) {
331
+			return $app !== 'files'; //we add this manually
332 332
 		});
333 333
 		sort($apps);
334 334
 		array_unshift($apps, 'files');
@@ -371,7 +371,7 @@  discard block
 block discarded – undo
371 371
 		);
372 372
 		$isDownloaded = $installer->isDownloaded($appId);
373 373
 
374
-		if(!$isDownloaded) {
374
+		if (!$isDownloaded) {
375 375
 			$installer->downloadApp($appId);
376 376
 		}
377 377
 
@@ -490,7 +490,7 @@  discard block
 block discarded – undo
490 490
 	 */
491 491
 	public static function findAppInDirectories($appId) {
492 492
 		$sanitizedAppId = self::cleanAppId($appId);
493
-		if($sanitizedAppId !== $appId) {
493
+		if ($sanitizedAppId !== $appId) {
494 494
 			return false;
495 495
 		}
496 496
 		static $app_dir = array();
@@ -501,7 +501,7 @@  discard block
 block discarded – undo
501 501
 
502 502
 		$possibleApps = array();
503 503
 		foreach (OC::$APPSROOTS as $dir) {
504
-			if (file_exists($dir['path'] . '/' . $appId)) {
504
+			if (file_exists($dir['path'].'/'.$appId)) {
505 505
 				$possibleApps[] = $dir;
506 506
 			}
507 507
 		}
@@ -542,7 +542,7 @@  discard block
 block discarded – undo
542 542
 		}
543 543
 
544 544
 		if (($dir = self::findAppInDirectories($appId)) != false) {
545
-			return $dir['path'] . '/' . $appId;
545
+			return $dir['path'].'/'.$appId;
546 546
 		}
547 547
 		return false;
548 548
 	}
@@ -556,7 +556,7 @@  discard block
 block discarded – undo
556 556
 	 */
557 557
 	public static function getAppWebPath($appId) {
558 558
 		if (($dir = self::findAppInDirectories($appId)) != false) {
559
-			return OC::$WEBROOT . $dir['url'] . '/' . $appId;
559
+			return OC::$WEBROOT.$dir['url'].'/'.$appId;
560 560
 		}
561 561
 		return false;
562 562
 	}
@@ -569,7 +569,7 @@  discard block
 block discarded – undo
569 569
 	 * @return string
570 570
 	 */
571 571
 	public static function getAppVersion($appId, $useCache = true) {
572
-		if($useCache && isset(self::$appVersion[$appId])) {
572
+		if ($useCache && isset(self::$appVersion[$appId])) {
573 573
 			return self::$appVersion[$appId];
574 574
 		}
575 575
 
@@ -585,7 +585,7 @@  discard block
 block discarded – undo
585 585
 	 * @return string
586 586
 	 */
587 587
 	public static function getAppVersionByPath($path) {
588
-		$infoFile = $path . '/appinfo/info.xml';
588
+		$infoFile = $path.'/appinfo/info.xml';
589 589
 		$appData = self::getAppInfo($infoFile, true);
590 590
 		return isset($appData['version']) ? $appData['version'] : '';
591 591
 	}
@@ -608,10 +608,10 @@  discard block
 block discarded – undo
608 608
 				return self::$appInfo[$appId];
609 609
 			}
610 610
 			$appPath = self::getAppPath($appId);
611
-			if($appPath === false) {
611
+			if ($appPath === false) {
612 612
 				return null;
613 613
 			}
614
-			$file = $appPath . '/appinfo/info.xml';
614
+			$file = $appPath.'/appinfo/info.xml';
615 615
 		}
616 616
 
617 617
 		$parser = new InfoParser(\OC::$server->getMemCacheFactory()->createLocal('core.appinfo'));
@@ -620,9 +620,9 @@  discard block
 block discarded – undo
620 620
 		if (is_array($data)) {
621 621
 			$data = OC_App::parseAppInfo($data, $lang);
622 622
 		}
623
-		if(isset($data['ocsid'])) {
623
+		if (isset($data['ocsid'])) {
624 624
 			$storedId = \OC::$server->getConfig()->getAppValue($appId, 'ocsid');
625
-			if($storedId !== '' && $storedId !== $data['ocsid']) {
625
+			if ($storedId !== '' && $storedId !== $data['ocsid']) {
626 626
 				$data['ocsid'] = $storedId;
627 627
 			}
628 628
 		}
@@ -714,7 +714,7 @@  discard block
 block discarded – undo
714 714
 	 * @param string $page
715 715
 	 */
716 716
 	public static function registerAdmin($app, $page) {
717
-		self::$adminForms[] = $app . '/' . $page . '.php';
717
+		self::$adminForms[] = $app.'/'.$page.'.php';
718 718
 	}
719 719
 
720 720
 	/**
@@ -723,7 +723,7 @@  discard block
 block discarded – undo
723 723
 	 * @param string $page
724 724
 	 */
725 725
 	public static function registerPersonal($app, $page) {
726
-		self::$personalForms[] = $app . '/' . $page . '.php';
726
+		self::$personalForms[] = $app.'/'.$page.'.php';
727 727
 	}
728 728
 
729 729
 	/**
@@ -752,7 +752,7 @@  discard block
 block discarded – undo
752 752
 
753 753
 		foreach (OC::$APPSROOTS as $apps_dir) {
754 754
 			if (!is_readable($apps_dir['path'])) {
755
-				\OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], \OCP\Util::WARN);
755
+				\OCP\Util::writeLog('core', 'unable to read app folder : '.$apps_dir['path'], \OCP\Util::WARN);
756 756
 				continue;
757 757
 			}
758 758
 			$dh = opendir($apps_dir['path']);
@@ -760,7 +760,7 @@  discard block
 block discarded – undo
760 760
 			if (is_resource($dh)) {
761 761
 				while (($file = readdir($dh)) !== false) {
762 762
 
763
-					if ($file[0] != '.' and is_dir($apps_dir['path'] . '/' . $file) and is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml')) {
763
+					if ($file[0] != '.' and is_dir($apps_dir['path'].'/'.$file) and is_file($apps_dir['path'].'/'.$file.'/appinfo/info.xml')) {
764 764
 
765 765
 						$apps[] = $file;
766 766
 					}
@@ -791,12 +791,12 @@  discard block
 block discarded – undo
791 791
 
792 792
 				$info = OC_App::getAppInfo($app, false, $langCode);
793 793
 				if (!is_array($info)) {
794
-					\OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', \OCP\Util::ERROR);
794
+					\OCP\Util::writeLog('core', 'Could not read app info file for app "'.$app.'"', \OCP\Util::ERROR);
795 795
 					continue;
796 796
 				}
797 797
 
798 798
 				if (!isset($info['name'])) {
799
-					\OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', \OCP\Util::ERROR);
799
+					\OCP\Util::writeLog('core', 'App id "'.$app.'" has no name in appinfo', \OCP\Util::ERROR);
800 800
 					continue;
801 801
 				}
802 802
 
@@ -823,13 +823,13 @@  discard block
 block discarded – undo
823 823
 				}
824 824
 
825 825
 				$appPath = self::getAppPath($app);
826
-				if($appPath !== false) {
827
-					$appIcon = $appPath . '/img/' . $app . '.svg';
826
+				if ($appPath !== false) {
827
+					$appIcon = $appPath.'/img/'.$app.'.svg';
828 828
 					if (file_exists($appIcon)) {
829
-						$info['preview'] = $urlGenerator->imagePath($app, $app . '.svg');
829
+						$info['preview'] = $urlGenerator->imagePath($app, $app.'.svg');
830 830
 						$info['previewAsIcon'] = true;
831 831
 					} else {
832
-						$appIcon = $appPath . '/img/app.svg';
832
+						$appIcon = $appPath.'/img/app.svg';
833 833
 						if (file_exists($appIcon)) {
834 834
 							$info['preview'] = $urlGenerator->imagePath($app, 'app.svg');
835 835
 							$info['previewAsIcon'] = true;
@@ -863,9 +863,9 @@  discard block
 block discarded – undo
863 863
 	 * @return string|false
864 864
 	 */
865 865
 	public static function getInternalAppIdByOcs($ocsID) {
866
-		if(is_numeric($ocsID)) {
866
+		if (is_numeric($ocsID)) {
867 867
 			$idArray = \OC::$server->getAppConfig()->getValues(false, 'ocsid');
868
-			if(array_search($ocsID, $idArray)) {
868
+			if (array_search($ocsID, $idArray)) {
869 869
 				return array_search($ocsID, $idArray);
870 870
 			}
871 871
 		}
@@ -969,7 +969,7 @@  discard block
 block discarded – undo
969 969
 	public static function getAppVersions() {
970 970
 		static $versions;
971 971
 
972
-		if(!$versions) {
972
+		if (!$versions) {
973 973
 			$appConfig = \OC::$server->getAppConfig();
974 974
 			$versions = $appConfig->getValues(false, 'installed_version');
975 975
 		}
@@ -991,7 +991,7 @@  discard block
 block discarded – undo
991 991
 		if ($app !== false) {
992 992
 			// check if the app is compatible with this version of ownCloud
993 993
 			$info = self::getAppInfo($app);
994
-			if(!is_array($info)) {
994
+			if (!is_array($info)) {
995 995
 				throw new \Exception(
996 996
 					$l->t('App "%s" cannot be installed because appinfo file cannot be read.',
997 997
 						[$info['name']]
@@ -1016,7 +1016,7 @@  discard block
 block discarded – undo
1016 1016
 				$config->setAppValue($app, 'ocsid', $appData['id']);
1017 1017
 			}
1018 1018
 
1019
-			if(isset($info['settings']) && is_array($info['settings'])) {
1019
+			if (isset($info['settings']) && is_array($info['settings'])) {
1020 1020
 				$appPath = self::getAppPath($app);
1021 1021
 				self::registerAutoloading($app, $appPath);
1022 1022
 				\OC::$server->getSettingsManager()->setupSettings($info['settings']);
@@ -1024,7 +1024,7 @@  discard block
 block discarded – undo
1024 1024
 
1025 1025
 			\OC_Hook::emit('OC_App', 'post_enable', array('app' => $app));
1026 1026
 		} else {
1027
-			if(empty($appName) ) {
1027
+			if (empty($appName)) {
1028 1028
 				throw new \Exception($l->t("No app name specified"));
1029 1029
 			} else {
1030 1030
 				throw new \Exception($l->t("App '%s' could not be installed!", $appName));
@@ -1042,7 +1042,7 @@  discard block
 block discarded – undo
1042 1042
 	 */
1043 1043
 	public static function updateApp($appId) {
1044 1044
 		$appPath = self::getAppPath($appId);
1045
-		if($appPath === false) {
1045
+		if ($appPath === false) {
1046 1046
 			return false;
1047 1047
 		}
1048 1048
 		self::registerAutoloading($appId, $appPath);
@@ -1050,8 +1050,8 @@  discard block
 block discarded – undo
1050 1050
 		$appData = self::getAppInfo($appId);
1051 1051
 		self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
1052 1052
 
1053
-		if (file_exists($appPath . '/appinfo/database.xml')) {
1054
-			OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
1053
+		if (file_exists($appPath.'/appinfo/database.xml')) {
1054
+			OC_DB::updateDbFromStructure($appPath.'/appinfo/database.xml');
1055 1055
 		} else {
1056 1056
 			$ms = new MigrationService($appId, \OC::$server->getDatabaseConnection());
1057 1057
 			$ms->migrate();
@@ -1062,26 +1062,26 @@  discard block
 block discarded – undo
1062 1062
 		unset(self::$appVersion[$appId]);
1063 1063
 
1064 1064
 		// run upgrade code
1065
-		if (file_exists($appPath . '/appinfo/update.php')) {
1065
+		if (file_exists($appPath.'/appinfo/update.php')) {
1066 1066
 			self::loadApp($appId);
1067
-			include $appPath . '/appinfo/update.php';
1067
+			include $appPath.'/appinfo/update.php';
1068 1068
 		}
1069 1069
 		self::setupBackgroundJobs($appData['background-jobs']);
1070
-		if(isset($appData['settings']) && is_array($appData['settings'])) {
1070
+		if (isset($appData['settings']) && is_array($appData['settings'])) {
1071 1071
 			\OC::$server->getSettingsManager()->setupSettings($appData['settings']);
1072 1072
 		}
1073 1073
 
1074 1074
 		//set remote/public handlers
1075 1075
 		if (array_key_exists('ocsid', $appData)) {
1076 1076
 			\OC::$server->getConfig()->setAppValue($appId, 'ocsid', $appData['ocsid']);
1077
-		} elseif(\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
1077
+		} elseif (\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
1078 1078
 			\OC::$server->getConfig()->deleteAppValue($appId, 'ocsid');
1079 1079
 		}
1080 1080
 		foreach ($appData['remote'] as $name => $path) {
1081
-			\OC::$server->getConfig()->setAppValue('core', 'remote_' . $name, $appId . '/' . $path);
1081
+			\OC::$server->getConfig()->setAppValue('core', 'remote_'.$name, $appId.'/'.$path);
1082 1082
 		}
1083 1083
 		foreach ($appData['public'] as $name => $path) {
1084
-			\OC::$server->getConfig()->setAppValue('core', 'public_' . $name, $appId . '/' . $path);
1084
+			\OC::$server->getConfig()->setAppValue('core', 'public_'.$name, $appId.'/'.$path);
1085 1085
 		}
1086 1086
 
1087 1087
 		self::setAppTypes($appId);
@@ -1151,17 +1151,17 @@  discard block
 block discarded – undo
1151 1151
 	public static function getStorage($appId) {
1152 1152
 		if (OC_App::isEnabled($appId)) { //sanity check
1153 1153
 			if (\OC::$server->getUserSession()->isLoggedIn()) {
1154
-				$view = new \OC\Files\View('/' . OC_User::getUser());
1154
+				$view = new \OC\Files\View('/'.OC_User::getUser());
1155 1155
 				if (!$view->file_exists($appId)) {
1156 1156
 					$view->mkdir($appId);
1157 1157
 				}
1158
-				return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
1158
+				return new \OC\Files\View('/'.OC_User::getUser().'/'.$appId);
1159 1159
 			} else {
1160
-				\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', \OCP\Util::ERROR);
1160
+				\OCP\Util::writeLog('core', 'Can\'t get app storage, app '.$appId.', user not logged in', \OCP\Util::ERROR);
1161 1161
 				return false;
1162 1162
 			}
1163 1163
 		} else {
1164
-			\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', \OCP\Util::ERROR);
1164
+			\OCP\Util::writeLog('core', 'Can\'t get app storage, app '.$appId.' not enabled', \OCP\Util::ERROR);
1165 1165
 			return false;
1166 1166
 		}
1167 1167
 	}
@@ -1193,9 +1193,9 @@  discard block
 block discarded – undo
1193 1193
 
1194 1194
 				if ($attributeLang === $similarLang) {
1195 1195
 					$similarLangFallback = $option['@value'];
1196
-				} else if (strpos($attributeLang, $similarLang . '_') === 0) {
1196
+				} else if (strpos($attributeLang, $similarLang.'_') === 0) {
1197 1197
 					if ($similarLangFallback === false) {
1198
-						$similarLangFallback =  $option['@value'];
1198
+						$similarLangFallback = $option['@value'];
1199 1199
 					}
1200 1200
 				}
1201 1201
 			} else {
@@ -1230,7 +1230,7 @@  discard block
 block discarded – undo
1230 1230
 			$data['description'] = trim(self::findBestL10NOption($data['description'], $lang));
1231 1231
 		} else if (isset($data['description']) && is_string($data['description'])) {
1232 1232
 			$data['description'] = trim($data['description']);
1233
-		} else  {
1233
+		} else {
1234 1234
 			$data['description'] = '';
1235 1235
 		}
1236 1236
 
Please login to merge, or discard this patch.
Indentation   +1196 added lines, -1196 removed lines patch added patch discarded remove patch
@@ -61,1200 +61,1200 @@
 block discarded – undo
61 61
  * upgrading and removing apps.
62 62
  */
63 63
 class OC_App {
64
-	static private $appVersion = [];
65
-	static private $adminForms = array();
66
-	static private $personalForms = array();
67
-	static private $appInfo = array();
68
-	static private $appTypes = array();
69
-	static private $loadedApps = array();
70
-	static private $altLogin = array();
71
-	static private $alreadyRegistered = [];
72
-	const officialApp = 200;
73
-
74
-	/**
75
-	 * clean the appId
76
-	 *
77
-	 * @param string|boolean $app AppId that needs to be cleaned
78
-	 * @return string
79
-	 */
80
-	public static function cleanAppId($app) {
81
-		return str_replace(array('\0', '/', '\\', '..'), '', $app);
82
-	}
83
-
84
-	/**
85
-	 * Check if an app is loaded
86
-	 *
87
-	 * @param string $app
88
-	 * @return bool
89
-	 */
90
-	public static function isAppLoaded($app) {
91
-		return in_array($app, self::$loadedApps, true);
92
-	}
93
-
94
-	/**
95
-	 * loads all apps
96
-	 *
97
-	 * @param string[] | string | null $types
98
-	 * @return bool
99
-	 *
100
-	 * This function walks through the ownCloud directory and loads all apps
101
-	 * it can find. A directory contains an app if the file /appinfo/info.xml
102
-	 * exists.
103
-	 *
104
-	 * if $types is set, only apps of those types will be loaded
105
-	 */
106
-	public static function loadApps($types = null) {
107
-		if (\OC::$server->getSystemConfig()->getValue('maintenance', false)) {
108
-			return false;
109
-		}
110
-		// Load the enabled apps here
111
-		$apps = self::getEnabledApps();
112
-
113
-		// Add each apps' folder as allowed class path
114
-		foreach($apps as $app) {
115
-			$path = self::getAppPath($app);
116
-			if($path !== false) {
117
-				self::registerAutoloading($app, $path);
118
-			}
119
-		}
120
-
121
-		// prevent app.php from printing output
122
-		ob_start();
123
-		foreach ($apps as $app) {
124
-			if ((is_null($types) or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) {
125
-				self::loadApp($app);
126
-			}
127
-		}
128
-		ob_end_clean();
129
-
130
-		return true;
131
-	}
132
-
133
-	/**
134
-	 * load a single app
135
-	 *
136
-	 * @param string $app
137
-	 */
138
-	public static function loadApp($app) {
139
-		self::$loadedApps[] = $app;
140
-		$appPath = self::getAppPath($app);
141
-		if($appPath === false) {
142
-			return;
143
-		}
144
-
145
-		// in case someone calls loadApp() directly
146
-		self::registerAutoloading($app, $appPath);
147
-
148
-		if (is_file($appPath . '/appinfo/app.php')) {
149
-			\OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
150
-			self::requireAppFile($app);
151
-			if (self::isType($app, array('authentication'))) {
152
-				// since authentication apps affect the "is app enabled for group" check,
153
-				// the enabled apps cache needs to be cleared to make sure that the
154
-				// next time getEnableApps() is called it will also include apps that were
155
-				// enabled for groups
156
-				self::$enabledAppsCache = array();
157
-			}
158
-			\OC::$server->getEventLogger()->end('load_app_' . $app);
159
-		}
160
-
161
-		$info = self::getAppInfo($app);
162
-		if (!empty($info['activity']['filters'])) {
163
-			foreach ($info['activity']['filters'] as $filter) {
164
-				\OC::$server->getActivityManager()->registerFilter($filter);
165
-			}
166
-		}
167
-		if (!empty($info['activity']['settings'])) {
168
-			foreach ($info['activity']['settings'] as $setting) {
169
-				\OC::$server->getActivityManager()->registerSetting($setting);
170
-			}
171
-		}
172
-		if (!empty($info['activity']['providers'])) {
173
-			foreach ($info['activity']['providers'] as $provider) {
174
-				\OC::$server->getActivityManager()->registerProvider($provider);
175
-			}
176
-		}
177
-		if (!empty($info['collaboration']['plugins'])) {
178
-			// deal with one or many plugin entries
179
-			$plugins = isset($info['collaboration']['plugins']['plugin']['@value']) ?
180
-				[$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin'];
181
-			foreach ($plugins as $plugin) {
182
-				if($plugin['@attributes']['type'] === 'collaborator-search') {
183
-					$pluginInfo = [
184
-						'shareType' => $plugin['@attributes']['share-type'],
185
-						'class' => $plugin['@value'],
186
-					];
187
-					\OC::$server->getCollaboratorSearch()->registerPlugin($pluginInfo);
188
-				}
189
-			}
190
-		}
191
-	}
192
-
193
-	/**
194
-	 * @internal
195
-	 * @param string $app
196
-	 * @param string $path
197
-	 */
198
-	public static function registerAutoloading($app, $path) {
199
-		$key = $app . '-' . $path;
200
-		if(isset(self::$alreadyRegistered[$key])) {
201
-			return;
202
-		}
203
-		self::$alreadyRegistered[$key] = true;
204
-		// Register on PSR-4 composer autoloader
205
-		$appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
206
-		\OC::$server->registerNamespace($app, $appNamespace);
207
-		\OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
208
-		if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
209
-			\OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);
210
-		}
211
-
212
-		// Register on legacy autoloader
213
-		\OC::$loader->addValidRoot($path);
214
-	}
215
-
216
-	/**
217
-	 * Load app.php from the given app
218
-	 *
219
-	 * @param string $app app name
220
-	 */
221
-	private static function requireAppFile($app) {
222
-		try {
223
-			// encapsulated here to avoid variable scope conflicts
224
-			require_once $app . '/appinfo/app.php';
225
-		} catch (Error $ex) {
226
-			\OC::$server->getLogger()->logException($ex);
227
-			$blacklist = \OC::$server->getAppManager()->getAlwaysEnabledApps();
228
-			if (!in_array($app, $blacklist)) {
229
-				self::disable($app);
230
-			}
231
-		}
232
-	}
233
-
234
-	/**
235
-	 * check if an app is of a specific type
236
-	 *
237
-	 * @param string $app
238
-	 * @param string|array $types
239
-	 * @return bool
240
-	 */
241
-	public static function isType($app, $types) {
242
-		if (is_string($types)) {
243
-			$types = array($types);
244
-		}
245
-		$appTypes = self::getAppTypes($app);
246
-		foreach ($types as $type) {
247
-			if (array_search($type, $appTypes) !== false) {
248
-				return true;
249
-			}
250
-		}
251
-		return false;
252
-	}
253
-
254
-	/**
255
-	 * get the types of an app
256
-	 *
257
-	 * @param string $app
258
-	 * @return array
259
-	 */
260
-	private static function getAppTypes($app) {
261
-		//load the cache
262
-		if (count(self::$appTypes) == 0) {
263
-			self::$appTypes = \OC::$server->getAppConfig()->getValues(false, 'types');
264
-		}
265
-
266
-		if (isset(self::$appTypes[$app])) {
267
-			return explode(',', self::$appTypes[$app]);
268
-		} else {
269
-			return array();
270
-		}
271
-	}
272
-
273
-	/**
274
-	 * read app types from info.xml and cache them in the database
275
-	 */
276
-	public static function setAppTypes($app) {
277
-		$appData = self::getAppInfo($app);
278
-		if(!is_array($appData)) {
279
-			return;
280
-		}
281
-
282
-		if (isset($appData['types'])) {
283
-			$appTypes = implode(',', $appData['types']);
284
-		} else {
285
-			$appTypes = '';
286
-			$appData['types'] = [];
287
-		}
288
-
289
-		\OC::$server->getAppConfig()->setValue($app, 'types', $appTypes);
290
-
291
-		if (\OC::$server->getAppManager()->hasProtectedAppType($appData['types'])) {
292
-			$enabled = \OC::$server->getAppConfig()->getValue($app, 'enabled', 'yes');
293
-			if ($enabled !== 'yes' && $enabled !== 'no') {
294
-				\OC::$server->getAppConfig()->setValue($app, 'enabled', 'yes');
295
-			}
296
-		}
297
-	}
298
-
299
-	/**
300
-	 * get all enabled apps
301
-	 */
302
-	protected static $enabledAppsCache = array();
303
-
304
-	/**
305
-	 * Returns apps enabled for the current user.
306
-	 *
307
-	 * @param bool $forceRefresh whether to refresh the cache
308
-	 * @param bool $all whether to return apps for all users, not only the
309
-	 * currently logged in one
310
-	 * @return string[]
311
-	 */
312
-	public static function getEnabledApps($forceRefresh = false, $all = false) {
313
-		if (!\OC::$server->getSystemConfig()->getValue('installed', false)) {
314
-			return array();
315
-		}
316
-		// in incognito mode or when logged out, $user will be false,
317
-		// which is also the case during an upgrade
318
-		$appManager = \OC::$server->getAppManager();
319
-		if ($all) {
320
-			$user = null;
321
-		} else {
322
-			$user = \OC::$server->getUserSession()->getUser();
323
-		}
324
-
325
-		if (is_null($user)) {
326
-			$apps = $appManager->getInstalledApps();
327
-		} else {
328
-			$apps = $appManager->getEnabledAppsForUser($user);
329
-		}
330
-		$apps = array_filter($apps, function ($app) {
331
-			return $app !== 'files';//we add this manually
332
-		});
333
-		sort($apps);
334
-		array_unshift($apps, 'files');
335
-		return $apps;
336
-	}
337
-
338
-	/**
339
-	 * checks whether or not an app is enabled
340
-	 *
341
-	 * @param string $app app
342
-	 * @return bool
343
-	 *
344
-	 * This function checks whether or not an app is enabled.
345
-	 */
346
-	public static function isEnabled($app) {
347
-		return \OC::$server->getAppManager()->isEnabledForUser($app);
348
-	}
349
-
350
-	/**
351
-	 * enables an app
352
-	 *
353
-	 * @param string $appId
354
-	 * @param array $groups (optional) when set, only these groups will have access to the app
355
-	 * @throws \Exception
356
-	 * @return void
357
-	 *
358
-	 * This function set an app as enabled in appconfig.
359
-	 */
360
-	public function enable($appId,
361
-						   $groups = null) {
362
-		self::$enabledAppsCache = []; // flush
363
-
364
-		// Check if app is already downloaded
365
-		$installer = new Installer(
366
-			\OC::$server->getAppFetcher(),
367
-			\OC::$server->getHTTPClientService(),
368
-			\OC::$server->getTempManager(),
369
-			\OC::$server->getLogger(),
370
-			\OC::$server->getConfig()
371
-		);
372
-		$isDownloaded = $installer->isDownloaded($appId);
373
-
374
-		if(!$isDownloaded) {
375
-			$installer->downloadApp($appId);
376
-		}
377
-
378
-		$installer->installApp($appId);
379
-
380
-		$appManager = \OC::$server->getAppManager();
381
-		if (!is_null($groups)) {
382
-			$groupManager = \OC::$server->getGroupManager();
383
-			$groupsList = [];
384
-			foreach ($groups as $group) {
385
-				$groupItem = $groupManager->get($group);
386
-				if ($groupItem instanceof \OCP\IGroup) {
387
-					$groupsList[] = $groupManager->get($group);
388
-				}
389
-			}
390
-			$appManager->enableAppForGroups($appId, $groupsList);
391
-		} else {
392
-			$appManager->enableApp($appId);
393
-		}
394
-	}
395
-
396
-	/**
397
-	 * @param string $app
398
-	 * @return bool
399
-	 */
400
-	public static function removeApp($app) {
401
-		if (\OC::$server->getAppManager()->isShipped($app)) {
402
-			return false;
403
-		}
404
-
405
-		$installer = new Installer(
406
-			\OC::$server->getAppFetcher(),
407
-			\OC::$server->getHTTPClientService(),
408
-			\OC::$server->getTempManager(),
409
-			\OC::$server->getLogger(),
410
-			\OC::$server->getConfig()
411
-		);
412
-		return $installer->removeApp($app);
413
-	}
414
-
415
-	/**
416
-	 * This function set an app as disabled in appconfig.
417
-	 *
418
-	 * @param string $app app
419
-	 * @throws Exception
420
-	 */
421
-	public static function disable($app) {
422
-		// flush
423
-		self::$enabledAppsCache = array();
424
-
425
-		// run uninstall steps
426
-		$appData = OC_App::getAppInfo($app);
427
-		if (!is_null($appData)) {
428
-			OC_App::executeRepairSteps($app, $appData['repair-steps']['uninstall']);
429
-		}
430
-
431
-		// emit disable hook - needed anymore ?
432
-		\OC_Hook::emit('OC_App', 'pre_disable', array('app' => $app));
433
-
434
-		// finally disable it
435
-		$appManager = \OC::$server->getAppManager();
436
-		$appManager->disableApp($app);
437
-	}
438
-
439
-	// This is private as well. It simply works, so don't ask for more details
440
-	private static function proceedNavigation($list) {
441
-		usort($list, function($a, $b) {
442
-			if (isset($a['order']) && isset($b['order'])) {
443
-				return ($a['order'] < $b['order']) ? -1 : 1;
444
-			} else if (isset($a['order']) || isset($b['order'])) {
445
-				return isset($a['order']) ? -1 : 1;
446
-			} else {
447
-				return ($a['name'] < $b['name']) ? -1 : 1;
448
-			}
449
-		});
450
-
451
-		$activeApp = OC::$server->getNavigationManager()->getActiveEntry();
452
-		foreach ($list as $index => &$navEntry) {
453
-			if ($navEntry['id'] == $activeApp) {
454
-				$navEntry['active'] = true;
455
-			} else {
456
-				$navEntry['active'] = false;
457
-			}
458
-		}
459
-		unset($navEntry);
460
-
461
-		return $list;
462
-	}
463
-
464
-	/**
465
-	 * Get the path where to install apps
466
-	 *
467
-	 * @return string|false
468
-	 */
469
-	public static function getInstallPath() {
470
-		if (\OC::$server->getSystemConfig()->getValue('appstoreenabled', true) == false) {
471
-			return false;
472
-		}
473
-
474
-		foreach (OC::$APPSROOTS as $dir) {
475
-			if (isset($dir['writable']) && $dir['writable'] === true) {
476
-				return $dir['path'];
477
-			}
478
-		}
479
-
480
-		\OCP\Util::writeLog('core', 'No application directories are marked as writable.', \OCP\Util::ERROR);
481
-		return null;
482
-	}
483
-
484
-
485
-	/**
486
-	 * search for an app in all app-directories
487
-	 *
488
-	 * @param string $appId
489
-	 * @return false|string
490
-	 */
491
-	public static function findAppInDirectories($appId) {
492
-		$sanitizedAppId = self::cleanAppId($appId);
493
-		if($sanitizedAppId !== $appId) {
494
-			return false;
495
-		}
496
-		static $app_dir = array();
497
-
498
-		if (isset($app_dir[$appId])) {
499
-			return $app_dir[$appId];
500
-		}
501
-
502
-		$possibleApps = array();
503
-		foreach (OC::$APPSROOTS as $dir) {
504
-			if (file_exists($dir['path'] . '/' . $appId)) {
505
-				$possibleApps[] = $dir;
506
-			}
507
-		}
508
-
509
-		if (empty($possibleApps)) {
510
-			return false;
511
-		} elseif (count($possibleApps) === 1) {
512
-			$dir = array_shift($possibleApps);
513
-			$app_dir[$appId] = $dir;
514
-			return $dir;
515
-		} else {
516
-			$versionToLoad = array();
517
-			foreach ($possibleApps as $possibleApp) {
518
-				$version = self::getAppVersionByPath($possibleApp['path']);
519
-				if (empty($versionToLoad) || version_compare($version, $versionToLoad['version'], '>')) {
520
-					$versionToLoad = array(
521
-						'dir' => $possibleApp,
522
-						'version' => $version,
523
-					);
524
-				}
525
-			}
526
-			$app_dir[$appId] = $versionToLoad['dir'];
527
-			return $versionToLoad['dir'];
528
-			//TODO - write test
529
-		}
530
-	}
531
-
532
-	/**
533
-	 * Get the directory for the given app.
534
-	 * If the app is defined in multiple directories, the first one is taken. (false if not found)
535
-	 *
536
-	 * @param string $appId
537
-	 * @return string|false
538
-	 */
539
-	public static function getAppPath($appId) {
540
-		if ($appId === null || trim($appId) === '') {
541
-			return false;
542
-		}
543
-
544
-		if (($dir = self::findAppInDirectories($appId)) != false) {
545
-			return $dir['path'] . '/' . $appId;
546
-		}
547
-		return false;
548
-	}
549
-
550
-	/**
551
-	 * Get the path for the given app on the access
552
-	 * If the app is defined in multiple directories, the first one is taken. (false if not found)
553
-	 *
554
-	 * @param string $appId
555
-	 * @return string|false
556
-	 */
557
-	public static function getAppWebPath($appId) {
558
-		if (($dir = self::findAppInDirectories($appId)) != false) {
559
-			return OC::$WEBROOT . $dir['url'] . '/' . $appId;
560
-		}
561
-		return false;
562
-	}
563
-
564
-	/**
565
-	 * get the last version of the app from appinfo/info.xml
566
-	 *
567
-	 * @param string $appId
568
-	 * @param bool $useCache
569
-	 * @return string
570
-	 */
571
-	public static function getAppVersion($appId, $useCache = true) {
572
-		if($useCache && isset(self::$appVersion[$appId])) {
573
-			return self::$appVersion[$appId];
574
-		}
575
-
576
-		$file = self::getAppPath($appId);
577
-		self::$appVersion[$appId] = ($file !== false) ? self::getAppVersionByPath($file) : '0';
578
-		return self::$appVersion[$appId];
579
-	}
580
-
581
-	/**
582
-	 * get app's version based on it's path
583
-	 *
584
-	 * @param string $path
585
-	 * @return string
586
-	 */
587
-	public static function getAppVersionByPath($path) {
588
-		$infoFile = $path . '/appinfo/info.xml';
589
-		$appData = self::getAppInfo($infoFile, true);
590
-		return isset($appData['version']) ? $appData['version'] : '';
591
-	}
592
-
593
-
594
-	/**
595
-	 * Read all app metadata from the info.xml file
596
-	 *
597
-	 * @param string $appId id of the app or the path of the info.xml file
598
-	 * @param bool $path
599
-	 * @param string $lang
600
-	 * @return array|null
601
-	 * @note all data is read from info.xml, not just pre-defined fields
602
-	 */
603
-	public static function getAppInfo($appId, $path = false, $lang = null) {
604
-		if ($path) {
605
-			$file = $appId;
606
-		} else {
607
-			if ($lang === null && isset(self::$appInfo[$appId])) {
608
-				return self::$appInfo[$appId];
609
-			}
610
-			$appPath = self::getAppPath($appId);
611
-			if($appPath === false) {
612
-				return null;
613
-			}
614
-			$file = $appPath . '/appinfo/info.xml';
615
-		}
616
-
617
-		$parser = new InfoParser(\OC::$server->getMemCacheFactory()->createLocal('core.appinfo'));
618
-		$data = $parser->parse($file);
619
-
620
-		if (is_array($data)) {
621
-			$data = OC_App::parseAppInfo($data, $lang);
622
-		}
623
-		if(isset($data['ocsid'])) {
624
-			$storedId = \OC::$server->getConfig()->getAppValue($appId, 'ocsid');
625
-			if($storedId !== '' && $storedId !== $data['ocsid']) {
626
-				$data['ocsid'] = $storedId;
627
-			}
628
-		}
629
-
630
-		if ($lang === null) {
631
-			self::$appInfo[$appId] = $data;
632
-		}
633
-
634
-		return $data;
635
-	}
636
-
637
-	/**
638
-	 * Returns the navigation
639
-	 *
640
-	 * @return array
641
-	 *
642
-	 * This function returns an array containing all entries added. The
643
-	 * entries are sorted by the key 'order' ascending. Additional to the keys
644
-	 * given for each app the following keys exist:
645
-	 *   - active: boolean, signals if the user is on this navigation entry
646
-	 */
647
-	public static function getNavigation() {
648
-		$entries = OC::$server->getNavigationManager()->getAll();
649
-		return self::proceedNavigation($entries);
650
-	}
651
-
652
-	/**
653
-	 * Returns the Settings Navigation
654
-	 *
655
-	 * @return string[]
656
-	 *
657
-	 * This function returns an array containing all settings pages added. The
658
-	 * entries are sorted by the key 'order' ascending.
659
-	 */
660
-	public static function getSettingsNavigation() {
661
-		$entries = OC::$server->getNavigationManager()->getAll('settings');
662
-		return self::proceedNavigation($entries);
663
-	}
664
-
665
-	/**
666
-	 * get the id of loaded app
667
-	 *
668
-	 * @return string
669
-	 */
670
-	public static function getCurrentApp() {
671
-		$request = \OC::$server->getRequest();
672
-		$script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1);
673
-		$topFolder = substr($script, 0, strpos($script, '/'));
674
-		if (empty($topFolder)) {
675
-			$path_info = $request->getPathInfo();
676
-			if ($path_info) {
677
-				$topFolder = substr($path_info, 1, strpos($path_info, '/', 1) - 1);
678
-			}
679
-		}
680
-		if ($topFolder == 'apps') {
681
-			$length = strlen($topFolder);
682
-			return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1);
683
-		} else {
684
-			return $topFolder;
685
-		}
686
-	}
687
-
688
-	/**
689
-	 * @param string $type
690
-	 * @return array
691
-	 */
692
-	public static function getForms($type) {
693
-		$forms = array();
694
-		switch ($type) {
695
-			case 'admin':
696
-				$source = self::$adminForms;
697
-				break;
698
-			case 'personal':
699
-				$source = self::$personalForms;
700
-				break;
701
-			default:
702
-				return array();
703
-		}
704
-		foreach ($source as $form) {
705
-			$forms[] = include $form;
706
-		}
707
-		return $forms;
708
-	}
709
-
710
-	/**
711
-	 * register an admin form to be shown
712
-	 *
713
-	 * @param string $app
714
-	 * @param string $page
715
-	 */
716
-	public static function registerAdmin($app, $page) {
717
-		self::$adminForms[] = $app . '/' . $page . '.php';
718
-	}
719
-
720
-	/**
721
-	 * register a personal form to be shown
722
-	 * @param string $app
723
-	 * @param string $page
724
-	 */
725
-	public static function registerPersonal($app, $page) {
726
-		self::$personalForms[] = $app . '/' . $page . '.php';
727
-	}
728
-
729
-	/**
730
-	 * @param array $entry
731
-	 */
732
-	public static function registerLogIn(array $entry) {
733
-		self::$altLogin[] = $entry;
734
-	}
735
-
736
-	/**
737
-	 * @return array
738
-	 */
739
-	public static function getAlternativeLogIns() {
740
-		return self::$altLogin;
741
-	}
742
-
743
-	/**
744
-	 * get a list of all apps in the apps folder
745
-	 *
746
-	 * @return array an array of app names (string IDs)
747
-	 * @todo: change the name of this method to getInstalledApps, which is more accurate
748
-	 */
749
-	public static function getAllApps() {
750
-
751
-		$apps = array();
752
-
753
-		foreach (OC::$APPSROOTS as $apps_dir) {
754
-			if (!is_readable($apps_dir['path'])) {
755
-				\OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], \OCP\Util::WARN);
756
-				continue;
757
-			}
758
-			$dh = opendir($apps_dir['path']);
759
-
760
-			if (is_resource($dh)) {
761
-				while (($file = readdir($dh)) !== false) {
762
-
763
-					if ($file[0] != '.' and is_dir($apps_dir['path'] . '/' . $file) and is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml')) {
764
-
765
-						$apps[] = $file;
766
-					}
767
-				}
768
-			}
769
-		}
770
-
771
-		$apps = array_unique($apps);
772
-
773
-		return $apps;
774
-	}
775
-
776
-	/**
777
-	 * List all apps, this is used in apps.php
778
-	 *
779
-	 * @return array
780
-	 */
781
-	public function listAllApps() {
782
-		$installedApps = OC_App::getAllApps();
783
-
784
-		$appManager = \OC::$server->getAppManager();
785
-		//we don't want to show configuration for these
786
-		$blacklist = $appManager->getAlwaysEnabledApps();
787
-		$appList = array();
788
-		$langCode = \OC::$server->getL10N('core')->getLanguageCode();
789
-		$urlGenerator = \OC::$server->getURLGenerator();
790
-
791
-		foreach ($installedApps as $app) {
792
-			if (array_search($app, $blacklist) === false) {
793
-
794
-				$info = OC_App::getAppInfo($app, false, $langCode);
795
-				if (!is_array($info)) {
796
-					\OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', \OCP\Util::ERROR);
797
-					continue;
798
-				}
799
-
800
-				if (!isset($info['name'])) {
801
-					\OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', \OCP\Util::ERROR);
802
-					continue;
803
-				}
804
-
805
-				$enabled = \OC::$server->getAppConfig()->getValue($app, 'enabled', 'no');
806
-				$info['groups'] = null;
807
-				if ($enabled === 'yes') {
808
-					$active = true;
809
-				} else if ($enabled === 'no') {
810
-					$active = false;
811
-				} else {
812
-					$active = true;
813
-					$info['groups'] = $enabled;
814
-				}
815
-
816
-				$info['active'] = $active;
817
-
818
-				if ($appManager->isShipped($app)) {
819
-					$info['internal'] = true;
820
-					$info['level'] = self::officialApp;
821
-					$info['removable'] = false;
822
-				} else {
823
-					$info['internal'] = false;
824
-					$info['removable'] = true;
825
-				}
826
-
827
-				$appPath = self::getAppPath($app);
828
-				if($appPath !== false) {
829
-					$appIcon = $appPath . '/img/' . $app . '.svg';
830
-					if (file_exists($appIcon)) {
831
-						$info['preview'] = $urlGenerator->imagePath($app, $app . '.svg');
832
-						$info['previewAsIcon'] = true;
833
-					} else {
834
-						$appIcon = $appPath . '/img/app.svg';
835
-						if (file_exists($appIcon)) {
836
-							$info['preview'] = $urlGenerator->imagePath($app, 'app.svg');
837
-							$info['previewAsIcon'] = true;
838
-						}
839
-					}
840
-				}
841
-				// fix documentation
842
-				if (isset($info['documentation']) && is_array($info['documentation'])) {
843
-					foreach ($info['documentation'] as $key => $url) {
844
-						// If it is not an absolute URL we assume it is a key
845
-						// i.e. admin-ldap will get converted to go.php?to=admin-ldap
846
-						if (stripos($url, 'https://') !== 0 && stripos($url, 'http://') !== 0) {
847
-							$url = $urlGenerator->linkToDocs($url);
848
-						}
849
-
850
-						$info['documentation'][$key] = $url;
851
-					}
852
-				}
853
-
854
-				$info['version'] = OC_App::getAppVersion($app);
855
-				$appList[] = $info;
856
-			}
857
-		}
858
-
859
-		return $appList;
860
-	}
861
-
862
-	/**
863
-	 * Returns the internal app ID or false
864
-	 * @param string $ocsID
865
-	 * @return string|false
866
-	 */
867
-	public static function getInternalAppIdByOcs($ocsID) {
868
-		if(is_numeric($ocsID)) {
869
-			$idArray = \OC::$server->getAppConfig()->getValues(false, 'ocsid');
870
-			if(array_search($ocsID, $idArray)) {
871
-				return array_search($ocsID, $idArray);
872
-			}
873
-		}
874
-		return false;
875
-	}
876
-
877
-	public static function shouldUpgrade($app) {
878
-		$versions = self::getAppVersions();
879
-		$currentVersion = OC_App::getAppVersion($app);
880
-		if ($currentVersion && isset($versions[$app])) {
881
-			$installedVersion = $versions[$app];
882
-			if (!version_compare($currentVersion, $installedVersion, '=')) {
883
-				return true;
884
-			}
885
-		}
886
-		return false;
887
-	}
888
-
889
-	/**
890
-	 * Adjust the number of version parts of $version1 to match
891
-	 * the number of version parts of $version2.
892
-	 *
893
-	 * @param string $version1 version to adjust
894
-	 * @param string $version2 version to take the number of parts from
895
-	 * @return string shortened $version1
896
-	 */
897
-	private static function adjustVersionParts($version1, $version2) {
898
-		$version1 = explode('.', $version1);
899
-		$version2 = explode('.', $version2);
900
-		// reduce $version1 to match the number of parts in $version2
901
-		while (count($version1) > count($version2)) {
902
-			array_pop($version1);
903
-		}
904
-		// if $version1 does not have enough parts, add some
905
-		while (count($version1) < count($version2)) {
906
-			$version1[] = '0';
907
-		}
908
-		return implode('.', $version1);
909
-	}
910
-
911
-	/**
912
-	 * Check whether the current ownCloud version matches the given
913
-	 * application's version requirements.
914
-	 *
915
-	 * The comparison is made based on the number of parts that the
916
-	 * app info version has. For example for ownCloud 6.0.3 if the
917
-	 * app info version is expecting version 6.0, the comparison is
918
-	 * made on the first two parts of the ownCloud version.
919
-	 * This means that it's possible to specify "requiremin" => 6
920
-	 * and "requiremax" => 6 and it will still match ownCloud 6.0.3.
921
-	 *
922
-	 * @param string $ocVersion ownCloud version to check against
923
-	 * @param array $appInfo app info (from xml)
924
-	 *
925
-	 * @return boolean true if compatible, otherwise false
926
-	 */
927
-	public static function isAppCompatible($ocVersion, $appInfo) {
928
-		$requireMin = '';
929
-		$requireMax = '';
930
-		if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) {
931
-			$requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version'];
932
-		} elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) {
933
-			$requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version'];
934
-		} else if (isset($appInfo['requiremin'])) {
935
-			$requireMin = $appInfo['requiremin'];
936
-		} else if (isset($appInfo['require'])) {
937
-			$requireMin = $appInfo['require'];
938
-		}
939
-
940
-		if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) {
941
-			$requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version'];
942
-		} elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) {
943
-			$requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version'];
944
-		} else if (isset($appInfo['requiremax'])) {
945
-			$requireMax = $appInfo['requiremax'];
946
-		}
947
-
948
-		if (is_array($ocVersion)) {
949
-			$ocVersion = implode('.', $ocVersion);
950
-		}
951
-
952
-		if (!empty($requireMin)
953
-			&& version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<')
954
-		) {
955
-
956
-			return false;
957
-		}
958
-
959
-		if (!empty($requireMax)
960
-			&& version_compare(self::adjustVersionParts($ocVersion, $requireMax), $requireMax, '>')
961
-		) {
962
-			return false;
963
-		}
964
-
965
-		return true;
966
-	}
967
-
968
-	/**
969
-	 * get the installed version of all apps
970
-	 */
971
-	public static function getAppVersions() {
972
-		static $versions;
973
-
974
-		if(!$versions) {
975
-			$appConfig = \OC::$server->getAppConfig();
976
-			$versions = $appConfig->getValues(false, 'installed_version');
977
-		}
978
-		return $versions;
979
-	}
980
-
981
-	/**
982
-	 * @param string $app
983
-	 * @param \OCP\IConfig $config
984
-	 * @param \OCP\IL10N $l
985
-	 * @return bool
986
-	 *
987
-	 * @throws Exception if app is not compatible with this version of ownCloud
988
-	 * @throws Exception if no app-name was specified
989
-	 */
990
-	public function installApp($app,
991
-							   \OCP\IConfig $config,
992
-							   \OCP\IL10N $l) {
993
-		if ($app !== false) {
994
-			// check if the app is compatible with this version of ownCloud
995
-			$info = self::getAppInfo($app);
996
-			if(!is_array($info)) {
997
-				throw new \Exception(
998
-					$l->t('App "%s" cannot be installed because appinfo file cannot be read.',
999
-						[$info['name']]
1000
-					)
1001
-				);
1002
-			}
1003
-
1004
-			$version = \OCP\Util::getVersion();
1005
-			if (!self::isAppCompatible($version, $info)) {
1006
-				throw new \Exception(
1007
-					$l->t('App "%s" cannot be installed because it is not compatible with this version of the server.',
1008
-						array($info['name'])
1009
-					)
1010
-				);
1011
-			}
1012
-
1013
-			// check for required dependencies
1014
-			self::checkAppDependencies($config, $l, $info);
1015
-
1016
-			$config->setAppValue($app, 'enabled', 'yes');
1017
-			if (isset($appData['id'])) {
1018
-				$config->setAppValue($app, 'ocsid', $appData['id']);
1019
-			}
1020
-
1021
-			if(isset($info['settings']) && is_array($info['settings'])) {
1022
-				$appPath = self::getAppPath($app);
1023
-				self::registerAutoloading($app, $appPath);
1024
-				\OC::$server->getSettingsManager()->setupSettings($info['settings']);
1025
-			}
1026
-
1027
-			\OC_Hook::emit('OC_App', 'post_enable', array('app' => $app));
1028
-		} else {
1029
-			if(empty($appName) ) {
1030
-				throw new \Exception($l->t("No app name specified"));
1031
-			} else {
1032
-				throw new \Exception($l->t("App '%s' could not be installed!", $appName));
1033
-			}
1034
-		}
1035
-
1036
-		return $app;
1037
-	}
1038
-
1039
-	/**
1040
-	 * update the database for the app and call the update script
1041
-	 *
1042
-	 * @param string $appId
1043
-	 * @return bool
1044
-	 */
1045
-	public static function updateApp($appId) {
1046
-		$appPath = self::getAppPath($appId);
1047
-		if($appPath === false) {
1048
-			return false;
1049
-		}
1050
-		self::registerAutoloading($appId, $appPath);
1051
-
1052
-		$appData = self::getAppInfo($appId);
1053
-		self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
1054
-
1055
-		if (file_exists($appPath . '/appinfo/database.xml')) {
1056
-			OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
1057
-		} else {
1058
-			$ms = new MigrationService($appId, \OC::$server->getDatabaseConnection());
1059
-			$ms->migrate();
1060
-		}
1061
-
1062
-		self::executeRepairSteps($appId, $appData['repair-steps']['post-migration']);
1063
-		self::setupLiveMigrations($appId, $appData['repair-steps']['live-migration']);
1064
-		unset(self::$appVersion[$appId]);
1065
-
1066
-		// run upgrade code
1067
-		if (file_exists($appPath . '/appinfo/update.php')) {
1068
-			self::loadApp($appId);
1069
-			include $appPath . '/appinfo/update.php';
1070
-		}
1071
-		self::setupBackgroundJobs($appData['background-jobs']);
1072
-		if(isset($appData['settings']) && is_array($appData['settings'])) {
1073
-			\OC::$server->getSettingsManager()->setupSettings($appData['settings']);
1074
-		}
1075
-
1076
-		//set remote/public handlers
1077
-		if (array_key_exists('ocsid', $appData)) {
1078
-			\OC::$server->getConfig()->setAppValue($appId, 'ocsid', $appData['ocsid']);
1079
-		} elseif(\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
1080
-			\OC::$server->getConfig()->deleteAppValue($appId, 'ocsid');
1081
-		}
1082
-		foreach ($appData['remote'] as $name => $path) {
1083
-			\OC::$server->getConfig()->setAppValue('core', 'remote_' . $name, $appId . '/' . $path);
1084
-		}
1085
-		foreach ($appData['public'] as $name => $path) {
1086
-			\OC::$server->getConfig()->setAppValue('core', 'public_' . $name, $appId . '/' . $path);
1087
-		}
1088
-
1089
-		self::setAppTypes($appId);
1090
-
1091
-		$version = \OC_App::getAppVersion($appId);
1092
-		\OC::$server->getAppConfig()->setValue($appId, 'installed_version', $version);
1093
-
1094
-		\OC::$server->getEventDispatcher()->dispatch(ManagerEvent::EVENT_APP_UPDATE, new ManagerEvent(
1095
-			ManagerEvent::EVENT_APP_UPDATE, $appId
1096
-		));
1097
-
1098
-		return true;
1099
-	}
1100
-
1101
-	/**
1102
-	 * @param string $appId
1103
-	 * @param string[] $steps
1104
-	 * @throws \OC\NeedsUpdateException
1105
-	 */
1106
-	public static function executeRepairSteps($appId, array $steps) {
1107
-		if (empty($steps)) {
1108
-			return;
1109
-		}
1110
-		// load the app
1111
-		self::loadApp($appId);
1112
-
1113
-		$dispatcher = OC::$server->getEventDispatcher();
1114
-
1115
-		// load the steps
1116
-		$r = new Repair([], $dispatcher);
1117
-		foreach ($steps as $step) {
1118
-			try {
1119
-				$r->addStep($step);
1120
-			} catch (Exception $ex) {
1121
-				$r->emit('\OC\Repair', 'error', [$ex->getMessage()]);
1122
-				\OC::$server->getLogger()->logException($ex);
1123
-			}
1124
-		}
1125
-		// run the steps
1126
-		$r->run();
1127
-	}
1128
-
1129
-	public static function setupBackgroundJobs(array $jobs) {
1130
-		$queue = \OC::$server->getJobList();
1131
-		foreach ($jobs as $job) {
1132
-			$queue->add($job);
1133
-		}
1134
-	}
1135
-
1136
-	/**
1137
-	 * @param string $appId
1138
-	 * @param string[] $steps
1139
-	 */
1140
-	private static function setupLiveMigrations($appId, array $steps) {
1141
-		$queue = \OC::$server->getJobList();
1142
-		foreach ($steps as $step) {
1143
-			$queue->add('OC\Migration\BackgroundRepair', [
1144
-				'app' => $appId,
1145
-				'step' => $step]);
1146
-		}
1147
-	}
1148
-
1149
-	/**
1150
-	 * @param string $appId
1151
-	 * @return \OC\Files\View|false
1152
-	 */
1153
-	public static function getStorage($appId) {
1154
-		if (OC_App::isEnabled($appId)) { //sanity check
1155
-			if (\OC::$server->getUserSession()->isLoggedIn()) {
1156
-				$view = new \OC\Files\View('/' . OC_User::getUser());
1157
-				if (!$view->file_exists($appId)) {
1158
-					$view->mkdir($appId);
1159
-				}
1160
-				return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
1161
-			} else {
1162
-				\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', \OCP\Util::ERROR);
1163
-				return false;
1164
-			}
1165
-		} else {
1166
-			\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', \OCP\Util::ERROR);
1167
-			return false;
1168
-		}
1169
-	}
1170
-
1171
-	protected static function findBestL10NOption($options, $lang) {
1172
-		$fallback = $similarLangFallback = $englishFallback = false;
1173
-
1174
-		$lang = strtolower($lang);
1175
-		$similarLang = $lang;
1176
-		if (strpos($similarLang, '_')) {
1177
-			// For "de_DE" we want to find "de" and the other way around
1178
-			$similarLang = substr($lang, 0, strpos($lang, '_'));
1179
-		}
1180
-
1181
-		foreach ($options as $option) {
1182
-			if (is_array($option)) {
1183
-				if ($fallback === false) {
1184
-					$fallback = $option['@value'];
1185
-				}
1186
-
1187
-				if (!isset($option['@attributes']['lang'])) {
1188
-					continue;
1189
-				}
1190
-
1191
-				$attributeLang = strtolower($option['@attributes']['lang']);
1192
-				if ($attributeLang === $lang) {
1193
-					return $option['@value'];
1194
-				}
1195
-
1196
-				if ($attributeLang === $similarLang) {
1197
-					$similarLangFallback = $option['@value'];
1198
-				} else if (strpos($attributeLang, $similarLang . '_') === 0) {
1199
-					if ($similarLangFallback === false) {
1200
-						$similarLangFallback =  $option['@value'];
1201
-					}
1202
-				}
1203
-			} else {
1204
-				$englishFallback = $option;
1205
-			}
1206
-		}
1207
-
1208
-		if ($similarLangFallback !== false) {
1209
-			return $similarLangFallback;
1210
-		} else if ($englishFallback !== false) {
1211
-			return $englishFallback;
1212
-		}
1213
-		return (string) $fallback;
1214
-	}
1215
-
1216
-	/**
1217
-	 * parses the app data array and enhanced the 'description' value
1218
-	 *
1219
-	 * @param array $data the app data
1220
-	 * @param string $lang
1221
-	 * @return array improved app data
1222
-	 */
1223
-	public static function parseAppInfo(array $data, $lang = null) {
1224
-
1225
-		if ($lang && isset($data['name']) && is_array($data['name'])) {
1226
-			$data['name'] = self::findBestL10NOption($data['name'], $lang);
1227
-		}
1228
-		if ($lang && isset($data['summary']) && is_array($data['summary'])) {
1229
-			$data['summary'] = self::findBestL10NOption($data['summary'], $lang);
1230
-		}
1231
-		if ($lang && isset($data['description']) && is_array($data['description'])) {
1232
-			$data['description'] = trim(self::findBestL10NOption($data['description'], $lang));
1233
-		} else if (isset($data['description']) && is_string($data['description'])) {
1234
-			$data['description'] = trim($data['description']);
1235
-		} else  {
1236
-			$data['description'] = '';
1237
-		}
1238
-
1239
-		return $data;
1240
-	}
1241
-
1242
-	/**
1243
-	 * @param \OCP\IConfig $config
1244
-	 * @param \OCP\IL10N $l
1245
-	 * @param array $info
1246
-	 * @throws \Exception
1247
-	 */
1248
-	public static function checkAppDependencies($config, $l, $info) {
1249
-		$dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
1250
-		$missing = $dependencyAnalyzer->analyze($info);
1251
-		if (!empty($missing)) {
1252
-			$missingMsg = implode(PHP_EOL, $missing);
1253
-			throw new \Exception(
1254
-				$l->t('App "%s" cannot be installed because the following dependencies are not fulfilled: %s',
1255
-					[$info['name'], $missingMsg]
1256
-				)
1257
-			);
1258
-		}
1259
-	}
64
+    static private $appVersion = [];
65
+    static private $adminForms = array();
66
+    static private $personalForms = array();
67
+    static private $appInfo = array();
68
+    static private $appTypes = array();
69
+    static private $loadedApps = array();
70
+    static private $altLogin = array();
71
+    static private $alreadyRegistered = [];
72
+    const officialApp = 200;
73
+
74
+    /**
75
+     * clean the appId
76
+     *
77
+     * @param string|boolean $app AppId that needs to be cleaned
78
+     * @return string
79
+     */
80
+    public static function cleanAppId($app) {
81
+        return str_replace(array('\0', '/', '\\', '..'), '', $app);
82
+    }
83
+
84
+    /**
85
+     * Check if an app is loaded
86
+     *
87
+     * @param string $app
88
+     * @return bool
89
+     */
90
+    public static function isAppLoaded($app) {
91
+        return in_array($app, self::$loadedApps, true);
92
+    }
93
+
94
+    /**
95
+     * loads all apps
96
+     *
97
+     * @param string[] | string | null $types
98
+     * @return bool
99
+     *
100
+     * This function walks through the ownCloud directory and loads all apps
101
+     * it can find. A directory contains an app if the file /appinfo/info.xml
102
+     * exists.
103
+     *
104
+     * if $types is set, only apps of those types will be loaded
105
+     */
106
+    public static function loadApps($types = null) {
107
+        if (\OC::$server->getSystemConfig()->getValue('maintenance', false)) {
108
+            return false;
109
+        }
110
+        // Load the enabled apps here
111
+        $apps = self::getEnabledApps();
112
+
113
+        // Add each apps' folder as allowed class path
114
+        foreach($apps as $app) {
115
+            $path = self::getAppPath($app);
116
+            if($path !== false) {
117
+                self::registerAutoloading($app, $path);
118
+            }
119
+        }
120
+
121
+        // prevent app.php from printing output
122
+        ob_start();
123
+        foreach ($apps as $app) {
124
+            if ((is_null($types) or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) {
125
+                self::loadApp($app);
126
+            }
127
+        }
128
+        ob_end_clean();
129
+
130
+        return true;
131
+    }
132
+
133
+    /**
134
+     * load a single app
135
+     *
136
+     * @param string $app
137
+     */
138
+    public static function loadApp($app) {
139
+        self::$loadedApps[] = $app;
140
+        $appPath = self::getAppPath($app);
141
+        if($appPath === false) {
142
+            return;
143
+        }
144
+
145
+        // in case someone calls loadApp() directly
146
+        self::registerAutoloading($app, $appPath);
147
+
148
+        if (is_file($appPath . '/appinfo/app.php')) {
149
+            \OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
150
+            self::requireAppFile($app);
151
+            if (self::isType($app, array('authentication'))) {
152
+                // since authentication apps affect the "is app enabled for group" check,
153
+                // the enabled apps cache needs to be cleared to make sure that the
154
+                // next time getEnableApps() is called it will also include apps that were
155
+                // enabled for groups
156
+                self::$enabledAppsCache = array();
157
+            }
158
+            \OC::$server->getEventLogger()->end('load_app_' . $app);
159
+        }
160
+
161
+        $info = self::getAppInfo($app);
162
+        if (!empty($info['activity']['filters'])) {
163
+            foreach ($info['activity']['filters'] as $filter) {
164
+                \OC::$server->getActivityManager()->registerFilter($filter);
165
+            }
166
+        }
167
+        if (!empty($info['activity']['settings'])) {
168
+            foreach ($info['activity']['settings'] as $setting) {
169
+                \OC::$server->getActivityManager()->registerSetting($setting);
170
+            }
171
+        }
172
+        if (!empty($info['activity']['providers'])) {
173
+            foreach ($info['activity']['providers'] as $provider) {
174
+                \OC::$server->getActivityManager()->registerProvider($provider);
175
+            }
176
+        }
177
+        if (!empty($info['collaboration']['plugins'])) {
178
+            // deal with one or many plugin entries
179
+            $plugins = isset($info['collaboration']['plugins']['plugin']['@value']) ?
180
+                [$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin'];
181
+            foreach ($plugins as $plugin) {
182
+                if($plugin['@attributes']['type'] === 'collaborator-search') {
183
+                    $pluginInfo = [
184
+                        'shareType' => $plugin['@attributes']['share-type'],
185
+                        'class' => $plugin['@value'],
186
+                    ];
187
+                    \OC::$server->getCollaboratorSearch()->registerPlugin($pluginInfo);
188
+                }
189
+            }
190
+        }
191
+    }
192
+
193
+    /**
194
+     * @internal
195
+     * @param string $app
196
+     * @param string $path
197
+     */
198
+    public static function registerAutoloading($app, $path) {
199
+        $key = $app . '-' . $path;
200
+        if(isset(self::$alreadyRegistered[$key])) {
201
+            return;
202
+        }
203
+        self::$alreadyRegistered[$key] = true;
204
+        // Register on PSR-4 composer autoloader
205
+        $appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
206
+        \OC::$server->registerNamespace($app, $appNamespace);
207
+        \OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
208
+        if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
209
+            \OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);
210
+        }
211
+
212
+        // Register on legacy autoloader
213
+        \OC::$loader->addValidRoot($path);
214
+    }
215
+
216
+    /**
217
+     * Load app.php from the given app
218
+     *
219
+     * @param string $app app name
220
+     */
221
+    private static function requireAppFile($app) {
222
+        try {
223
+            // encapsulated here to avoid variable scope conflicts
224
+            require_once $app . '/appinfo/app.php';
225
+        } catch (Error $ex) {
226
+            \OC::$server->getLogger()->logException($ex);
227
+            $blacklist = \OC::$server->getAppManager()->getAlwaysEnabledApps();
228
+            if (!in_array($app, $blacklist)) {
229
+                self::disable($app);
230
+            }
231
+        }
232
+    }
233
+
234
+    /**
235
+     * check if an app is of a specific type
236
+     *
237
+     * @param string $app
238
+     * @param string|array $types
239
+     * @return bool
240
+     */
241
+    public static function isType($app, $types) {
242
+        if (is_string($types)) {
243
+            $types = array($types);
244
+        }
245
+        $appTypes = self::getAppTypes($app);
246
+        foreach ($types as $type) {
247
+            if (array_search($type, $appTypes) !== false) {
248
+                return true;
249
+            }
250
+        }
251
+        return false;
252
+    }
253
+
254
+    /**
255
+     * get the types of an app
256
+     *
257
+     * @param string $app
258
+     * @return array
259
+     */
260
+    private static function getAppTypes($app) {
261
+        //load the cache
262
+        if (count(self::$appTypes) == 0) {
263
+            self::$appTypes = \OC::$server->getAppConfig()->getValues(false, 'types');
264
+        }
265
+
266
+        if (isset(self::$appTypes[$app])) {
267
+            return explode(',', self::$appTypes[$app]);
268
+        } else {
269
+            return array();
270
+        }
271
+    }
272
+
273
+    /**
274
+     * read app types from info.xml and cache them in the database
275
+     */
276
+    public static function setAppTypes($app) {
277
+        $appData = self::getAppInfo($app);
278
+        if(!is_array($appData)) {
279
+            return;
280
+        }
281
+
282
+        if (isset($appData['types'])) {
283
+            $appTypes = implode(',', $appData['types']);
284
+        } else {
285
+            $appTypes = '';
286
+            $appData['types'] = [];
287
+        }
288
+
289
+        \OC::$server->getAppConfig()->setValue($app, 'types', $appTypes);
290
+
291
+        if (\OC::$server->getAppManager()->hasProtectedAppType($appData['types'])) {
292
+            $enabled = \OC::$server->getAppConfig()->getValue($app, 'enabled', 'yes');
293
+            if ($enabled !== 'yes' && $enabled !== 'no') {
294
+                \OC::$server->getAppConfig()->setValue($app, 'enabled', 'yes');
295
+            }
296
+        }
297
+    }
298
+
299
+    /**
300
+     * get all enabled apps
301
+     */
302
+    protected static $enabledAppsCache = array();
303
+
304
+    /**
305
+     * Returns apps enabled for the current user.
306
+     *
307
+     * @param bool $forceRefresh whether to refresh the cache
308
+     * @param bool $all whether to return apps for all users, not only the
309
+     * currently logged in one
310
+     * @return string[]
311
+     */
312
+    public static function getEnabledApps($forceRefresh = false, $all = false) {
313
+        if (!\OC::$server->getSystemConfig()->getValue('installed', false)) {
314
+            return array();
315
+        }
316
+        // in incognito mode or when logged out, $user will be false,
317
+        // which is also the case during an upgrade
318
+        $appManager = \OC::$server->getAppManager();
319
+        if ($all) {
320
+            $user = null;
321
+        } else {
322
+            $user = \OC::$server->getUserSession()->getUser();
323
+        }
324
+
325
+        if (is_null($user)) {
326
+            $apps = $appManager->getInstalledApps();
327
+        } else {
328
+            $apps = $appManager->getEnabledAppsForUser($user);
329
+        }
330
+        $apps = array_filter($apps, function ($app) {
331
+            return $app !== 'files';//we add this manually
332
+        });
333
+        sort($apps);
334
+        array_unshift($apps, 'files');
335
+        return $apps;
336
+    }
337
+
338
+    /**
339
+     * checks whether or not an app is enabled
340
+     *
341
+     * @param string $app app
342
+     * @return bool
343
+     *
344
+     * This function checks whether or not an app is enabled.
345
+     */
346
+    public static function isEnabled($app) {
347
+        return \OC::$server->getAppManager()->isEnabledForUser($app);
348
+    }
349
+
350
+    /**
351
+     * enables an app
352
+     *
353
+     * @param string $appId
354
+     * @param array $groups (optional) when set, only these groups will have access to the app
355
+     * @throws \Exception
356
+     * @return void
357
+     *
358
+     * This function set an app as enabled in appconfig.
359
+     */
360
+    public function enable($appId,
361
+                            $groups = null) {
362
+        self::$enabledAppsCache = []; // flush
363
+
364
+        // Check if app is already downloaded
365
+        $installer = new Installer(
366
+            \OC::$server->getAppFetcher(),
367
+            \OC::$server->getHTTPClientService(),
368
+            \OC::$server->getTempManager(),
369
+            \OC::$server->getLogger(),
370
+            \OC::$server->getConfig()
371
+        );
372
+        $isDownloaded = $installer->isDownloaded($appId);
373
+
374
+        if(!$isDownloaded) {
375
+            $installer->downloadApp($appId);
376
+        }
377
+
378
+        $installer->installApp($appId);
379
+
380
+        $appManager = \OC::$server->getAppManager();
381
+        if (!is_null($groups)) {
382
+            $groupManager = \OC::$server->getGroupManager();
383
+            $groupsList = [];
384
+            foreach ($groups as $group) {
385
+                $groupItem = $groupManager->get($group);
386
+                if ($groupItem instanceof \OCP\IGroup) {
387
+                    $groupsList[] = $groupManager->get($group);
388
+                }
389
+            }
390
+            $appManager->enableAppForGroups($appId, $groupsList);
391
+        } else {
392
+            $appManager->enableApp($appId);
393
+        }
394
+    }
395
+
396
+    /**
397
+     * @param string $app
398
+     * @return bool
399
+     */
400
+    public static function removeApp($app) {
401
+        if (\OC::$server->getAppManager()->isShipped($app)) {
402
+            return false;
403
+        }
404
+
405
+        $installer = new Installer(
406
+            \OC::$server->getAppFetcher(),
407
+            \OC::$server->getHTTPClientService(),
408
+            \OC::$server->getTempManager(),
409
+            \OC::$server->getLogger(),
410
+            \OC::$server->getConfig()
411
+        );
412
+        return $installer->removeApp($app);
413
+    }
414
+
415
+    /**
416
+     * This function set an app as disabled in appconfig.
417
+     *
418
+     * @param string $app app
419
+     * @throws Exception
420
+     */
421
+    public static function disable($app) {
422
+        // flush
423
+        self::$enabledAppsCache = array();
424
+
425
+        // run uninstall steps
426
+        $appData = OC_App::getAppInfo($app);
427
+        if (!is_null($appData)) {
428
+            OC_App::executeRepairSteps($app, $appData['repair-steps']['uninstall']);
429
+        }
430
+
431
+        // emit disable hook - needed anymore ?
432
+        \OC_Hook::emit('OC_App', 'pre_disable', array('app' => $app));
433
+
434
+        // finally disable it
435
+        $appManager = \OC::$server->getAppManager();
436
+        $appManager->disableApp($app);
437
+    }
438
+
439
+    // This is private as well. It simply works, so don't ask for more details
440
+    private static function proceedNavigation($list) {
441
+        usort($list, function($a, $b) {
442
+            if (isset($a['order']) && isset($b['order'])) {
443
+                return ($a['order'] < $b['order']) ? -1 : 1;
444
+            } else if (isset($a['order']) || isset($b['order'])) {
445
+                return isset($a['order']) ? -1 : 1;
446
+            } else {
447
+                return ($a['name'] < $b['name']) ? -1 : 1;
448
+            }
449
+        });
450
+
451
+        $activeApp = OC::$server->getNavigationManager()->getActiveEntry();
452
+        foreach ($list as $index => &$navEntry) {
453
+            if ($navEntry['id'] == $activeApp) {
454
+                $navEntry['active'] = true;
455
+            } else {
456
+                $navEntry['active'] = false;
457
+            }
458
+        }
459
+        unset($navEntry);
460
+
461
+        return $list;
462
+    }
463
+
464
+    /**
465
+     * Get the path where to install apps
466
+     *
467
+     * @return string|false
468
+     */
469
+    public static function getInstallPath() {
470
+        if (\OC::$server->getSystemConfig()->getValue('appstoreenabled', true) == false) {
471
+            return false;
472
+        }
473
+
474
+        foreach (OC::$APPSROOTS as $dir) {
475
+            if (isset($dir['writable']) && $dir['writable'] === true) {
476
+                return $dir['path'];
477
+            }
478
+        }
479
+
480
+        \OCP\Util::writeLog('core', 'No application directories are marked as writable.', \OCP\Util::ERROR);
481
+        return null;
482
+    }
483
+
484
+
485
+    /**
486
+     * search for an app in all app-directories
487
+     *
488
+     * @param string $appId
489
+     * @return false|string
490
+     */
491
+    public static function findAppInDirectories($appId) {
492
+        $sanitizedAppId = self::cleanAppId($appId);
493
+        if($sanitizedAppId !== $appId) {
494
+            return false;
495
+        }
496
+        static $app_dir = array();
497
+
498
+        if (isset($app_dir[$appId])) {
499
+            return $app_dir[$appId];
500
+        }
501
+
502
+        $possibleApps = array();
503
+        foreach (OC::$APPSROOTS as $dir) {
504
+            if (file_exists($dir['path'] . '/' . $appId)) {
505
+                $possibleApps[] = $dir;
506
+            }
507
+        }
508
+
509
+        if (empty($possibleApps)) {
510
+            return false;
511
+        } elseif (count($possibleApps) === 1) {
512
+            $dir = array_shift($possibleApps);
513
+            $app_dir[$appId] = $dir;
514
+            return $dir;
515
+        } else {
516
+            $versionToLoad = array();
517
+            foreach ($possibleApps as $possibleApp) {
518
+                $version = self::getAppVersionByPath($possibleApp['path']);
519
+                if (empty($versionToLoad) || version_compare($version, $versionToLoad['version'], '>')) {
520
+                    $versionToLoad = array(
521
+                        'dir' => $possibleApp,
522
+                        'version' => $version,
523
+                    );
524
+                }
525
+            }
526
+            $app_dir[$appId] = $versionToLoad['dir'];
527
+            return $versionToLoad['dir'];
528
+            //TODO - write test
529
+        }
530
+    }
531
+
532
+    /**
533
+     * Get the directory for the given app.
534
+     * If the app is defined in multiple directories, the first one is taken. (false if not found)
535
+     *
536
+     * @param string $appId
537
+     * @return string|false
538
+     */
539
+    public static function getAppPath($appId) {
540
+        if ($appId === null || trim($appId) === '') {
541
+            return false;
542
+        }
543
+
544
+        if (($dir = self::findAppInDirectories($appId)) != false) {
545
+            return $dir['path'] . '/' . $appId;
546
+        }
547
+        return false;
548
+    }
549
+
550
+    /**
551
+     * Get the path for the given app on the access
552
+     * If the app is defined in multiple directories, the first one is taken. (false if not found)
553
+     *
554
+     * @param string $appId
555
+     * @return string|false
556
+     */
557
+    public static function getAppWebPath($appId) {
558
+        if (($dir = self::findAppInDirectories($appId)) != false) {
559
+            return OC::$WEBROOT . $dir['url'] . '/' . $appId;
560
+        }
561
+        return false;
562
+    }
563
+
564
+    /**
565
+     * get the last version of the app from appinfo/info.xml
566
+     *
567
+     * @param string $appId
568
+     * @param bool $useCache
569
+     * @return string
570
+     */
571
+    public static function getAppVersion($appId, $useCache = true) {
572
+        if($useCache && isset(self::$appVersion[$appId])) {
573
+            return self::$appVersion[$appId];
574
+        }
575
+
576
+        $file = self::getAppPath($appId);
577
+        self::$appVersion[$appId] = ($file !== false) ? self::getAppVersionByPath($file) : '0';
578
+        return self::$appVersion[$appId];
579
+    }
580
+
581
+    /**
582
+     * get app's version based on it's path
583
+     *
584
+     * @param string $path
585
+     * @return string
586
+     */
587
+    public static function getAppVersionByPath($path) {
588
+        $infoFile = $path . '/appinfo/info.xml';
589
+        $appData = self::getAppInfo($infoFile, true);
590
+        return isset($appData['version']) ? $appData['version'] : '';
591
+    }
592
+
593
+
594
+    /**
595
+     * Read all app metadata from the info.xml file
596
+     *
597
+     * @param string $appId id of the app or the path of the info.xml file
598
+     * @param bool $path
599
+     * @param string $lang
600
+     * @return array|null
601
+     * @note all data is read from info.xml, not just pre-defined fields
602
+     */
603
+    public static function getAppInfo($appId, $path = false, $lang = null) {
604
+        if ($path) {
605
+            $file = $appId;
606
+        } else {
607
+            if ($lang === null && isset(self::$appInfo[$appId])) {
608
+                return self::$appInfo[$appId];
609
+            }
610
+            $appPath = self::getAppPath($appId);
611
+            if($appPath === false) {
612
+                return null;
613
+            }
614
+            $file = $appPath . '/appinfo/info.xml';
615
+        }
616
+
617
+        $parser = new InfoParser(\OC::$server->getMemCacheFactory()->createLocal('core.appinfo'));
618
+        $data = $parser->parse($file);
619
+
620
+        if (is_array($data)) {
621
+            $data = OC_App::parseAppInfo($data, $lang);
622
+        }
623
+        if(isset($data['ocsid'])) {
624
+            $storedId = \OC::$server->getConfig()->getAppValue($appId, 'ocsid');
625
+            if($storedId !== '' && $storedId !== $data['ocsid']) {
626
+                $data['ocsid'] = $storedId;
627
+            }
628
+        }
629
+
630
+        if ($lang === null) {
631
+            self::$appInfo[$appId] = $data;
632
+        }
633
+
634
+        return $data;
635
+    }
636
+
637
+    /**
638
+     * Returns the navigation
639
+     *
640
+     * @return array
641
+     *
642
+     * This function returns an array containing all entries added. The
643
+     * entries are sorted by the key 'order' ascending. Additional to the keys
644
+     * given for each app the following keys exist:
645
+     *   - active: boolean, signals if the user is on this navigation entry
646
+     */
647
+    public static function getNavigation() {
648
+        $entries = OC::$server->getNavigationManager()->getAll();
649
+        return self::proceedNavigation($entries);
650
+    }
651
+
652
+    /**
653
+     * Returns the Settings Navigation
654
+     *
655
+     * @return string[]
656
+     *
657
+     * This function returns an array containing all settings pages added. The
658
+     * entries are sorted by the key 'order' ascending.
659
+     */
660
+    public static function getSettingsNavigation() {
661
+        $entries = OC::$server->getNavigationManager()->getAll('settings');
662
+        return self::proceedNavigation($entries);
663
+    }
664
+
665
+    /**
666
+     * get the id of loaded app
667
+     *
668
+     * @return string
669
+     */
670
+    public static function getCurrentApp() {
671
+        $request = \OC::$server->getRequest();
672
+        $script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1);
673
+        $topFolder = substr($script, 0, strpos($script, '/'));
674
+        if (empty($topFolder)) {
675
+            $path_info = $request->getPathInfo();
676
+            if ($path_info) {
677
+                $topFolder = substr($path_info, 1, strpos($path_info, '/', 1) - 1);
678
+            }
679
+        }
680
+        if ($topFolder == 'apps') {
681
+            $length = strlen($topFolder);
682
+            return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1);
683
+        } else {
684
+            return $topFolder;
685
+        }
686
+    }
687
+
688
+    /**
689
+     * @param string $type
690
+     * @return array
691
+     */
692
+    public static function getForms($type) {
693
+        $forms = array();
694
+        switch ($type) {
695
+            case 'admin':
696
+                $source = self::$adminForms;
697
+                break;
698
+            case 'personal':
699
+                $source = self::$personalForms;
700
+                break;
701
+            default:
702
+                return array();
703
+        }
704
+        foreach ($source as $form) {
705
+            $forms[] = include $form;
706
+        }
707
+        return $forms;
708
+    }
709
+
710
+    /**
711
+     * register an admin form to be shown
712
+     *
713
+     * @param string $app
714
+     * @param string $page
715
+     */
716
+    public static function registerAdmin($app, $page) {
717
+        self::$adminForms[] = $app . '/' . $page . '.php';
718
+    }
719
+
720
+    /**
721
+     * register a personal form to be shown
722
+     * @param string $app
723
+     * @param string $page
724
+     */
725
+    public static function registerPersonal($app, $page) {
726
+        self::$personalForms[] = $app . '/' . $page . '.php';
727
+    }
728
+
729
+    /**
730
+     * @param array $entry
731
+     */
732
+    public static function registerLogIn(array $entry) {
733
+        self::$altLogin[] = $entry;
734
+    }
735
+
736
+    /**
737
+     * @return array
738
+     */
739
+    public static function getAlternativeLogIns() {
740
+        return self::$altLogin;
741
+    }
742
+
743
+    /**
744
+     * get a list of all apps in the apps folder
745
+     *
746
+     * @return array an array of app names (string IDs)
747
+     * @todo: change the name of this method to getInstalledApps, which is more accurate
748
+     */
749
+    public static function getAllApps() {
750
+
751
+        $apps = array();
752
+
753
+        foreach (OC::$APPSROOTS as $apps_dir) {
754
+            if (!is_readable($apps_dir['path'])) {
755
+                \OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], \OCP\Util::WARN);
756
+                continue;
757
+            }
758
+            $dh = opendir($apps_dir['path']);
759
+
760
+            if (is_resource($dh)) {
761
+                while (($file = readdir($dh)) !== false) {
762
+
763
+                    if ($file[0] != '.' and is_dir($apps_dir['path'] . '/' . $file) and is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml')) {
764
+
765
+                        $apps[] = $file;
766
+                    }
767
+                }
768
+            }
769
+        }
770
+
771
+        $apps = array_unique($apps);
772
+
773
+        return $apps;
774
+    }
775
+
776
+    /**
777
+     * List all apps, this is used in apps.php
778
+     *
779
+     * @return array
780
+     */
781
+    public function listAllApps() {
782
+        $installedApps = OC_App::getAllApps();
783
+
784
+        $appManager = \OC::$server->getAppManager();
785
+        //we don't want to show configuration for these
786
+        $blacklist = $appManager->getAlwaysEnabledApps();
787
+        $appList = array();
788
+        $langCode = \OC::$server->getL10N('core')->getLanguageCode();
789
+        $urlGenerator = \OC::$server->getURLGenerator();
790
+
791
+        foreach ($installedApps as $app) {
792
+            if (array_search($app, $blacklist) === false) {
793
+
794
+                $info = OC_App::getAppInfo($app, false, $langCode);
795
+                if (!is_array($info)) {
796
+                    \OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', \OCP\Util::ERROR);
797
+                    continue;
798
+                }
799
+
800
+                if (!isset($info['name'])) {
801
+                    \OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', \OCP\Util::ERROR);
802
+                    continue;
803
+                }
804
+
805
+                $enabled = \OC::$server->getAppConfig()->getValue($app, 'enabled', 'no');
806
+                $info['groups'] = null;
807
+                if ($enabled === 'yes') {
808
+                    $active = true;
809
+                } else if ($enabled === 'no') {
810
+                    $active = false;
811
+                } else {
812
+                    $active = true;
813
+                    $info['groups'] = $enabled;
814
+                }
815
+
816
+                $info['active'] = $active;
817
+
818
+                if ($appManager->isShipped($app)) {
819
+                    $info['internal'] = true;
820
+                    $info['level'] = self::officialApp;
821
+                    $info['removable'] = false;
822
+                } else {
823
+                    $info['internal'] = false;
824
+                    $info['removable'] = true;
825
+                }
826
+
827
+                $appPath = self::getAppPath($app);
828
+                if($appPath !== false) {
829
+                    $appIcon = $appPath . '/img/' . $app . '.svg';
830
+                    if (file_exists($appIcon)) {
831
+                        $info['preview'] = $urlGenerator->imagePath($app, $app . '.svg');
832
+                        $info['previewAsIcon'] = true;
833
+                    } else {
834
+                        $appIcon = $appPath . '/img/app.svg';
835
+                        if (file_exists($appIcon)) {
836
+                            $info['preview'] = $urlGenerator->imagePath($app, 'app.svg');
837
+                            $info['previewAsIcon'] = true;
838
+                        }
839
+                    }
840
+                }
841
+                // fix documentation
842
+                if (isset($info['documentation']) && is_array($info['documentation'])) {
843
+                    foreach ($info['documentation'] as $key => $url) {
844
+                        // If it is not an absolute URL we assume it is a key
845
+                        // i.e. admin-ldap will get converted to go.php?to=admin-ldap
846
+                        if (stripos($url, 'https://') !== 0 && stripos($url, 'http://') !== 0) {
847
+                            $url = $urlGenerator->linkToDocs($url);
848
+                        }
849
+
850
+                        $info['documentation'][$key] = $url;
851
+                    }
852
+                }
853
+
854
+                $info['version'] = OC_App::getAppVersion($app);
855
+                $appList[] = $info;
856
+            }
857
+        }
858
+
859
+        return $appList;
860
+    }
861
+
862
+    /**
863
+     * Returns the internal app ID or false
864
+     * @param string $ocsID
865
+     * @return string|false
866
+     */
867
+    public static function getInternalAppIdByOcs($ocsID) {
868
+        if(is_numeric($ocsID)) {
869
+            $idArray = \OC::$server->getAppConfig()->getValues(false, 'ocsid');
870
+            if(array_search($ocsID, $idArray)) {
871
+                return array_search($ocsID, $idArray);
872
+            }
873
+        }
874
+        return false;
875
+    }
876
+
877
+    public static function shouldUpgrade($app) {
878
+        $versions = self::getAppVersions();
879
+        $currentVersion = OC_App::getAppVersion($app);
880
+        if ($currentVersion && isset($versions[$app])) {
881
+            $installedVersion = $versions[$app];
882
+            if (!version_compare($currentVersion, $installedVersion, '=')) {
883
+                return true;
884
+            }
885
+        }
886
+        return false;
887
+    }
888
+
889
+    /**
890
+     * Adjust the number of version parts of $version1 to match
891
+     * the number of version parts of $version2.
892
+     *
893
+     * @param string $version1 version to adjust
894
+     * @param string $version2 version to take the number of parts from
895
+     * @return string shortened $version1
896
+     */
897
+    private static function adjustVersionParts($version1, $version2) {
898
+        $version1 = explode('.', $version1);
899
+        $version2 = explode('.', $version2);
900
+        // reduce $version1 to match the number of parts in $version2
901
+        while (count($version1) > count($version2)) {
902
+            array_pop($version1);
903
+        }
904
+        // if $version1 does not have enough parts, add some
905
+        while (count($version1) < count($version2)) {
906
+            $version1[] = '0';
907
+        }
908
+        return implode('.', $version1);
909
+    }
910
+
911
+    /**
912
+     * Check whether the current ownCloud version matches the given
913
+     * application's version requirements.
914
+     *
915
+     * The comparison is made based on the number of parts that the
916
+     * app info version has. For example for ownCloud 6.0.3 if the
917
+     * app info version is expecting version 6.0, the comparison is
918
+     * made on the first two parts of the ownCloud version.
919
+     * This means that it's possible to specify "requiremin" => 6
920
+     * and "requiremax" => 6 and it will still match ownCloud 6.0.3.
921
+     *
922
+     * @param string $ocVersion ownCloud version to check against
923
+     * @param array $appInfo app info (from xml)
924
+     *
925
+     * @return boolean true if compatible, otherwise false
926
+     */
927
+    public static function isAppCompatible($ocVersion, $appInfo) {
928
+        $requireMin = '';
929
+        $requireMax = '';
930
+        if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) {
931
+            $requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version'];
932
+        } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) {
933
+            $requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version'];
934
+        } else if (isset($appInfo['requiremin'])) {
935
+            $requireMin = $appInfo['requiremin'];
936
+        } else if (isset($appInfo['require'])) {
937
+            $requireMin = $appInfo['require'];
938
+        }
939
+
940
+        if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) {
941
+            $requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version'];
942
+        } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) {
943
+            $requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version'];
944
+        } else if (isset($appInfo['requiremax'])) {
945
+            $requireMax = $appInfo['requiremax'];
946
+        }
947
+
948
+        if (is_array($ocVersion)) {
949
+            $ocVersion = implode('.', $ocVersion);
950
+        }
951
+
952
+        if (!empty($requireMin)
953
+            && version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<')
954
+        ) {
955
+
956
+            return false;
957
+        }
958
+
959
+        if (!empty($requireMax)
960
+            && version_compare(self::adjustVersionParts($ocVersion, $requireMax), $requireMax, '>')
961
+        ) {
962
+            return false;
963
+        }
964
+
965
+        return true;
966
+    }
967
+
968
+    /**
969
+     * get the installed version of all apps
970
+     */
971
+    public static function getAppVersions() {
972
+        static $versions;
973
+
974
+        if(!$versions) {
975
+            $appConfig = \OC::$server->getAppConfig();
976
+            $versions = $appConfig->getValues(false, 'installed_version');
977
+        }
978
+        return $versions;
979
+    }
980
+
981
+    /**
982
+     * @param string $app
983
+     * @param \OCP\IConfig $config
984
+     * @param \OCP\IL10N $l
985
+     * @return bool
986
+     *
987
+     * @throws Exception if app is not compatible with this version of ownCloud
988
+     * @throws Exception if no app-name was specified
989
+     */
990
+    public function installApp($app,
991
+                                \OCP\IConfig $config,
992
+                                \OCP\IL10N $l) {
993
+        if ($app !== false) {
994
+            // check if the app is compatible with this version of ownCloud
995
+            $info = self::getAppInfo($app);
996
+            if(!is_array($info)) {
997
+                throw new \Exception(
998
+                    $l->t('App "%s" cannot be installed because appinfo file cannot be read.',
999
+                        [$info['name']]
1000
+                    )
1001
+                );
1002
+            }
1003
+
1004
+            $version = \OCP\Util::getVersion();
1005
+            if (!self::isAppCompatible($version, $info)) {
1006
+                throw new \Exception(
1007
+                    $l->t('App "%s" cannot be installed because it is not compatible with this version of the server.',
1008
+                        array($info['name'])
1009
+                    )
1010
+                );
1011
+            }
1012
+
1013
+            // check for required dependencies
1014
+            self::checkAppDependencies($config, $l, $info);
1015
+
1016
+            $config->setAppValue($app, 'enabled', 'yes');
1017
+            if (isset($appData['id'])) {
1018
+                $config->setAppValue($app, 'ocsid', $appData['id']);
1019
+            }
1020
+
1021
+            if(isset($info['settings']) && is_array($info['settings'])) {
1022
+                $appPath = self::getAppPath($app);
1023
+                self::registerAutoloading($app, $appPath);
1024
+                \OC::$server->getSettingsManager()->setupSettings($info['settings']);
1025
+            }
1026
+
1027
+            \OC_Hook::emit('OC_App', 'post_enable', array('app' => $app));
1028
+        } else {
1029
+            if(empty($appName) ) {
1030
+                throw new \Exception($l->t("No app name specified"));
1031
+            } else {
1032
+                throw new \Exception($l->t("App '%s' could not be installed!", $appName));
1033
+            }
1034
+        }
1035
+
1036
+        return $app;
1037
+    }
1038
+
1039
+    /**
1040
+     * update the database for the app and call the update script
1041
+     *
1042
+     * @param string $appId
1043
+     * @return bool
1044
+     */
1045
+    public static function updateApp($appId) {
1046
+        $appPath = self::getAppPath($appId);
1047
+        if($appPath === false) {
1048
+            return false;
1049
+        }
1050
+        self::registerAutoloading($appId, $appPath);
1051
+
1052
+        $appData = self::getAppInfo($appId);
1053
+        self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
1054
+
1055
+        if (file_exists($appPath . '/appinfo/database.xml')) {
1056
+            OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
1057
+        } else {
1058
+            $ms = new MigrationService($appId, \OC::$server->getDatabaseConnection());
1059
+            $ms->migrate();
1060
+        }
1061
+
1062
+        self::executeRepairSteps($appId, $appData['repair-steps']['post-migration']);
1063
+        self::setupLiveMigrations($appId, $appData['repair-steps']['live-migration']);
1064
+        unset(self::$appVersion[$appId]);
1065
+
1066
+        // run upgrade code
1067
+        if (file_exists($appPath . '/appinfo/update.php')) {
1068
+            self::loadApp($appId);
1069
+            include $appPath . '/appinfo/update.php';
1070
+        }
1071
+        self::setupBackgroundJobs($appData['background-jobs']);
1072
+        if(isset($appData['settings']) && is_array($appData['settings'])) {
1073
+            \OC::$server->getSettingsManager()->setupSettings($appData['settings']);
1074
+        }
1075
+
1076
+        //set remote/public handlers
1077
+        if (array_key_exists('ocsid', $appData)) {
1078
+            \OC::$server->getConfig()->setAppValue($appId, 'ocsid', $appData['ocsid']);
1079
+        } elseif(\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
1080
+            \OC::$server->getConfig()->deleteAppValue($appId, 'ocsid');
1081
+        }
1082
+        foreach ($appData['remote'] as $name => $path) {
1083
+            \OC::$server->getConfig()->setAppValue('core', 'remote_' . $name, $appId . '/' . $path);
1084
+        }
1085
+        foreach ($appData['public'] as $name => $path) {
1086
+            \OC::$server->getConfig()->setAppValue('core', 'public_' . $name, $appId . '/' . $path);
1087
+        }
1088
+
1089
+        self::setAppTypes($appId);
1090
+
1091
+        $version = \OC_App::getAppVersion($appId);
1092
+        \OC::$server->getAppConfig()->setValue($appId, 'installed_version', $version);
1093
+
1094
+        \OC::$server->getEventDispatcher()->dispatch(ManagerEvent::EVENT_APP_UPDATE, new ManagerEvent(
1095
+            ManagerEvent::EVENT_APP_UPDATE, $appId
1096
+        ));
1097
+
1098
+        return true;
1099
+    }
1100
+
1101
+    /**
1102
+     * @param string $appId
1103
+     * @param string[] $steps
1104
+     * @throws \OC\NeedsUpdateException
1105
+     */
1106
+    public static function executeRepairSteps($appId, array $steps) {
1107
+        if (empty($steps)) {
1108
+            return;
1109
+        }
1110
+        // load the app
1111
+        self::loadApp($appId);
1112
+
1113
+        $dispatcher = OC::$server->getEventDispatcher();
1114
+
1115
+        // load the steps
1116
+        $r = new Repair([], $dispatcher);
1117
+        foreach ($steps as $step) {
1118
+            try {
1119
+                $r->addStep($step);
1120
+            } catch (Exception $ex) {
1121
+                $r->emit('\OC\Repair', 'error', [$ex->getMessage()]);
1122
+                \OC::$server->getLogger()->logException($ex);
1123
+            }
1124
+        }
1125
+        // run the steps
1126
+        $r->run();
1127
+    }
1128
+
1129
+    public static function setupBackgroundJobs(array $jobs) {
1130
+        $queue = \OC::$server->getJobList();
1131
+        foreach ($jobs as $job) {
1132
+            $queue->add($job);
1133
+        }
1134
+    }
1135
+
1136
+    /**
1137
+     * @param string $appId
1138
+     * @param string[] $steps
1139
+     */
1140
+    private static function setupLiveMigrations($appId, array $steps) {
1141
+        $queue = \OC::$server->getJobList();
1142
+        foreach ($steps as $step) {
1143
+            $queue->add('OC\Migration\BackgroundRepair', [
1144
+                'app' => $appId,
1145
+                'step' => $step]);
1146
+        }
1147
+    }
1148
+
1149
+    /**
1150
+     * @param string $appId
1151
+     * @return \OC\Files\View|false
1152
+     */
1153
+    public static function getStorage($appId) {
1154
+        if (OC_App::isEnabled($appId)) { //sanity check
1155
+            if (\OC::$server->getUserSession()->isLoggedIn()) {
1156
+                $view = new \OC\Files\View('/' . OC_User::getUser());
1157
+                if (!$view->file_exists($appId)) {
1158
+                    $view->mkdir($appId);
1159
+                }
1160
+                return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
1161
+            } else {
1162
+                \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', \OCP\Util::ERROR);
1163
+                return false;
1164
+            }
1165
+        } else {
1166
+            \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', \OCP\Util::ERROR);
1167
+            return false;
1168
+        }
1169
+    }
1170
+
1171
+    protected static function findBestL10NOption($options, $lang) {
1172
+        $fallback = $similarLangFallback = $englishFallback = false;
1173
+
1174
+        $lang = strtolower($lang);
1175
+        $similarLang = $lang;
1176
+        if (strpos($similarLang, '_')) {
1177
+            // For "de_DE" we want to find "de" and the other way around
1178
+            $similarLang = substr($lang, 0, strpos($lang, '_'));
1179
+        }
1180
+
1181
+        foreach ($options as $option) {
1182
+            if (is_array($option)) {
1183
+                if ($fallback === false) {
1184
+                    $fallback = $option['@value'];
1185
+                }
1186
+
1187
+                if (!isset($option['@attributes']['lang'])) {
1188
+                    continue;
1189
+                }
1190
+
1191
+                $attributeLang = strtolower($option['@attributes']['lang']);
1192
+                if ($attributeLang === $lang) {
1193
+                    return $option['@value'];
1194
+                }
1195
+
1196
+                if ($attributeLang === $similarLang) {
1197
+                    $similarLangFallback = $option['@value'];
1198
+                } else if (strpos($attributeLang, $similarLang . '_') === 0) {
1199
+                    if ($similarLangFallback === false) {
1200
+                        $similarLangFallback =  $option['@value'];
1201
+                    }
1202
+                }
1203
+            } else {
1204
+                $englishFallback = $option;
1205
+            }
1206
+        }
1207
+
1208
+        if ($similarLangFallback !== false) {
1209
+            return $similarLangFallback;
1210
+        } else if ($englishFallback !== false) {
1211
+            return $englishFallback;
1212
+        }
1213
+        return (string) $fallback;
1214
+    }
1215
+
1216
+    /**
1217
+     * parses the app data array and enhanced the 'description' value
1218
+     *
1219
+     * @param array $data the app data
1220
+     * @param string $lang
1221
+     * @return array improved app data
1222
+     */
1223
+    public static function parseAppInfo(array $data, $lang = null) {
1224
+
1225
+        if ($lang && isset($data['name']) && is_array($data['name'])) {
1226
+            $data['name'] = self::findBestL10NOption($data['name'], $lang);
1227
+        }
1228
+        if ($lang && isset($data['summary']) && is_array($data['summary'])) {
1229
+            $data['summary'] = self::findBestL10NOption($data['summary'], $lang);
1230
+        }
1231
+        if ($lang && isset($data['description']) && is_array($data['description'])) {
1232
+            $data['description'] = trim(self::findBestL10NOption($data['description'], $lang));
1233
+        } else if (isset($data['description']) && is_string($data['description'])) {
1234
+            $data['description'] = trim($data['description']);
1235
+        } else  {
1236
+            $data['description'] = '';
1237
+        }
1238
+
1239
+        return $data;
1240
+    }
1241
+
1242
+    /**
1243
+     * @param \OCP\IConfig $config
1244
+     * @param \OCP\IL10N $l
1245
+     * @param array $info
1246
+     * @throws \Exception
1247
+     */
1248
+    public static function checkAppDependencies($config, $l, $info) {
1249
+        $dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
1250
+        $missing = $dependencyAnalyzer->analyze($info);
1251
+        if (!empty($missing)) {
1252
+            $missingMsg = implode(PHP_EOL, $missing);
1253
+            throw new \Exception(
1254
+                $l->t('App "%s" cannot be installed because the following dependencies are not fulfilled: %s',
1255
+                    [$info['name'], $missingMsg]
1256
+                )
1257
+            );
1258
+        }
1259
+    }
1260 1260
 }
Please login to merge, or discard this patch.
lib/private/Files/Node/File.php 2 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -31,7 +31,7 @@
 block discarded – undo
31 31
 	 * Creates a Folder that represents a non-existing path
32 32
 	 *
33 33
 	 * @param string $path path
34
-	 * @return string non-existing node class
34
+	 * @return NonExistingFile non-existing node class
35 35
 	 */
36 36
 	protected function createNonExistingNode($path) {
37 37
 		return new NonExistingFile($this->root, $this->view, $path);
Please login to merge, or discard this patch.
Indentation   +102 added lines, -102 removed lines patch added patch discarded remove patch
@@ -29,113 +29,113 @@
 block discarded – undo
29 29
 use OCP\Files\NotPermittedException;
30 30
 
31 31
 class File extends Node implements \OCP\Files\File {
32
-	/**
33
-	 * Creates a Folder that represents a non-existing path
34
-	 *
35
-	 * @param string $path path
36
-	 * @return string non-existing node class
37
-	 */
38
-	protected function createNonExistingNode($path) {
39
-		return new NonExistingFile($this->root, $this->view, $path);
40
-	}
32
+    /**
33
+     * Creates a Folder that represents a non-existing path
34
+     *
35
+     * @param string $path path
36
+     * @return string non-existing node class
37
+     */
38
+    protected function createNonExistingNode($path) {
39
+        return new NonExistingFile($this->root, $this->view, $path);
40
+    }
41 41
 
42
-	/**
43
-	 * @return string
44
-	 * @throws \OCP\Files\NotPermittedException
45
-	 */
46
-	public function getContent() {
47
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_READ)) {
48
-			/**
49
-			 * @var \OC\Files\Storage\Storage $storage;
50
-			 */
51
-			return $this->view->file_get_contents($this->path);
52
-		} else {
53
-			throw new NotPermittedException();
54
-		}
55
-	}
42
+    /**
43
+     * @return string
44
+     * @throws \OCP\Files\NotPermittedException
45
+     */
46
+    public function getContent() {
47
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_READ)) {
48
+            /**
49
+             * @var \OC\Files\Storage\Storage $storage;
50
+             */
51
+            return $this->view->file_get_contents($this->path);
52
+        } else {
53
+            throw new NotPermittedException();
54
+        }
55
+    }
56 56
 
57
-	/**
58
-	 * @param string $data
59
-	 * @throws \OCP\Files\NotPermittedException
60
-	 */
61
-	public function putContent($data) {
62
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE)) {
63
-			$this->sendHooks(array('preWrite'));
64
-			$this->view->file_put_contents($this->path, $data);
65
-			$this->fileInfo = null;
66
-			$this->sendHooks(array('postWrite'));
67
-		} else {
68
-			throw new NotPermittedException();
69
-		}
70
-	}
57
+    /**
58
+     * @param string $data
59
+     * @throws \OCP\Files\NotPermittedException
60
+     */
61
+    public function putContent($data) {
62
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE)) {
63
+            $this->sendHooks(array('preWrite'));
64
+            $this->view->file_put_contents($this->path, $data);
65
+            $this->fileInfo = null;
66
+            $this->sendHooks(array('postWrite'));
67
+        } else {
68
+            throw new NotPermittedException();
69
+        }
70
+    }
71 71
 
72
-	/**
73
-	 * @param string $mode
74
-	 * @return resource
75
-	 * @throws \OCP\Files\NotPermittedException
76
-	 */
77
-	public function fopen($mode) {
78
-		$preHooks = array();
79
-		$postHooks = array();
80
-		$requiredPermissions = \OCP\Constants::PERMISSION_READ;
81
-		switch ($mode) {
82
-			case 'r+':
83
-			case 'rb+':
84
-			case 'w+':
85
-			case 'wb+':
86
-			case 'x+':
87
-			case 'xb+':
88
-			case 'a+':
89
-			case 'ab+':
90
-			case 'w':
91
-			case 'wb':
92
-			case 'x':
93
-			case 'xb':
94
-			case 'a':
95
-			case 'ab':
96
-				$preHooks[] = 'preWrite';
97
-				$postHooks[] = 'postWrite';
98
-				$requiredPermissions |= \OCP\Constants::PERMISSION_UPDATE;
99
-				break;
100
-		}
72
+    /**
73
+     * @param string $mode
74
+     * @return resource
75
+     * @throws \OCP\Files\NotPermittedException
76
+     */
77
+    public function fopen($mode) {
78
+        $preHooks = array();
79
+        $postHooks = array();
80
+        $requiredPermissions = \OCP\Constants::PERMISSION_READ;
81
+        switch ($mode) {
82
+            case 'r+':
83
+            case 'rb+':
84
+            case 'w+':
85
+            case 'wb+':
86
+            case 'x+':
87
+            case 'xb+':
88
+            case 'a+':
89
+            case 'ab+':
90
+            case 'w':
91
+            case 'wb':
92
+            case 'x':
93
+            case 'xb':
94
+            case 'a':
95
+            case 'ab':
96
+                $preHooks[] = 'preWrite';
97
+                $postHooks[] = 'postWrite';
98
+                $requiredPermissions |= \OCP\Constants::PERMISSION_UPDATE;
99
+                break;
100
+        }
101 101
 
102
-		if ($this->checkPermissions($requiredPermissions)) {
103
-			$this->sendHooks($preHooks);
104
-			$result = $this->view->fopen($this->path, $mode);
105
-			$this->sendHooks($postHooks);
106
-			return $result;
107
-		} else {
108
-			throw new NotPermittedException();
109
-		}
110
-	}
102
+        if ($this->checkPermissions($requiredPermissions)) {
103
+            $this->sendHooks($preHooks);
104
+            $result = $this->view->fopen($this->path, $mode);
105
+            $this->sendHooks($postHooks);
106
+            return $result;
107
+        } else {
108
+            throw new NotPermittedException();
109
+        }
110
+    }
111 111
 
112
-	public function delete() {
113
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
114
-			$this->sendHooks(array('preDelete'));
115
-			$fileInfo = $this->getFileInfo();
116
-			$this->view->unlink($this->path);
117
-			$nonExisting = new NonExistingFile($this->root, $this->view, $this->path, $fileInfo);
118
-			$this->root->emit('\OC\Files', 'postDelete', array($nonExisting));
119
-			$this->exists = false;
120
-			$this->fileInfo = null;
121
-		} else {
122
-			throw new NotPermittedException();
123
-		}
124
-	}
112
+    public function delete() {
113
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
114
+            $this->sendHooks(array('preDelete'));
115
+            $fileInfo = $this->getFileInfo();
116
+            $this->view->unlink($this->path);
117
+            $nonExisting = new NonExistingFile($this->root, $this->view, $this->path, $fileInfo);
118
+            $this->root->emit('\OC\Files', 'postDelete', array($nonExisting));
119
+            $this->exists = false;
120
+            $this->fileInfo = null;
121
+        } else {
122
+            throw new NotPermittedException();
123
+        }
124
+    }
125 125
 
126
-	/**
127
-	 * @param string $type
128
-	 * @param bool $raw
129
-	 * @return string
130
-	 */
131
-	public function hash($type, $raw = false) {
132
-		return $this->view->hash($type, $this->path, $raw);
133
-	}
126
+    /**
127
+     * @param string $type
128
+     * @param bool $raw
129
+     * @return string
130
+     */
131
+    public function hash($type, $raw = false) {
132
+        return $this->view->hash($type, $this->path, $raw);
133
+    }
134 134
 
135
-	/**
136
-	 * @inheritdoc
137
-	 */
138
-	public function getChecksum() {
139
-		return $this->getFileInfo()->getChecksum();
140
-	}
135
+    /**
136
+     * @inheritdoc
137
+     */
138
+    public function getChecksum() {
139
+        return $this->getFileInfo()->getChecksum();
140
+    }
141 141
 }
Please login to merge, or discard this patch.
lib/private/Files/Node/Folder.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -37,7 +37,7 @@
 block discarded – undo
37 37
 	 * Creates a Folder that represents a non-existing path
38 38
 	 *
39 39
 	 * @param string $path path
40
-	 * @return string non-existing node class
40
+	 * @return NonExistingFolder non-existing node class
41 41
 	 */
42 42
 	protected function createNonExistingNode($path) {
43 43
 		return new NonExistingFolder($this->root, $this->view, $path);
Please login to merge, or discard this patch.
Indentation   +395 added lines, -395 removed lines patch added patch discarded remove patch
@@ -36,399 +36,399 @@
 block discarded – undo
36 36
 use OCP\Files\Search\ISearchOperator;
37 37
 
38 38
 class Folder extends Node implements \OCP\Files\Folder {
39
-	/**
40
-	 * Creates a Folder that represents a non-existing path
41
-	 *
42
-	 * @param string $path path
43
-	 * @return string non-existing node class
44
-	 */
45
-	protected function createNonExistingNode($path) {
46
-		return new NonExistingFolder($this->root, $this->view, $path);
47
-	}
48
-
49
-	/**
50
-	 * @param string $path path relative to the folder
51
-	 * @return string
52
-	 * @throws \OCP\Files\NotPermittedException
53
-	 */
54
-	public function getFullPath($path) {
55
-		if (!$this->isValidPath($path)) {
56
-			throw new NotPermittedException('Invalid path');
57
-		}
58
-		return $this->path . $this->normalizePath($path);
59
-	}
60
-
61
-	/**
62
-	 * @param string $path
63
-	 * @return string
64
-	 */
65
-	public function getRelativePath($path) {
66
-		if ($this->path === '' or $this->path === '/') {
67
-			return $this->normalizePath($path);
68
-		}
69
-		if ($path === $this->path) {
70
-			return '/';
71
-		} else if (strpos($path, $this->path . '/') !== 0) {
72
-			return null;
73
-		} else {
74
-			$path = substr($path, strlen($this->path));
75
-			return $this->normalizePath($path);
76
-		}
77
-	}
78
-
79
-	/**
80
-	 * check if a node is a (grand-)child of the folder
81
-	 *
82
-	 * @param \OC\Files\Node\Node $node
83
-	 * @return bool
84
-	 */
85
-	public function isSubNode($node) {
86
-		return strpos($node->getPath(), $this->path . '/') === 0;
87
-	}
88
-
89
-	/**
90
-	 * get the content of this directory
91
-	 *
92
-	 * @throws \OCP\Files\NotFoundException
93
-	 * @return Node[]
94
-	 */
95
-	public function getDirectoryListing() {
96
-		$folderContent = $this->view->getDirectoryContent($this->path);
97
-
98
-		return array_map(function (FileInfo $info) {
99
-			if ($info->getMimetype() === 'httpd/unix-directory') {
100
-				return new Folder($this->root, $this->view, $info->getPath(), $info);
101
-			} else {
102
-				return new File($this->root, $this->view, $info->getPath(), $info);
103
-			}
104
-		}, $folderContent);
105
-	}
106
-
107
-	/**
108
-	 * @param string $path
109
-	 * @param FileInfo $info
110
-	 * @return File|Folder
111
-	 */
112
-	protected function createNode($path, FileInfo $info = null) {
113
-		if (is_null($info)) {
114
-			$isDir = $this->view->is_dir($path);
115
-		} else {
116
-			$isDir = $info->getType() === FileInfo::TYPE_FOLDER;
117
-		}
118
-		if ($isDir) {
119
-			return new Folder($this->root, $this->view, $path, $info);
120
-		} else {
121
-			return new File($this->root, $this->view, $path, $info);
122
-		}
123
-	}
124
-
125
-	/**
126
-	 * Get the node at $path
127
-	 *
128
-	 * @param string $path
129
-	 * @return \OC\Files\Node\Node
130
-	 * @throws \OCP\Files\NotFoundException
131
-	 */
132
-	public function get($path) {
133
-		return $this->root->get($this->getFullPath($path));
134
-	}
135
-
136
-	/**
137
-	 * @param string $path
138
-	 * @return bool
139
-	 */
140
-	public function nodeExists($path) {
141
-		try {
142
-			$this->get($path);
143
-			return true;
144
-		} catch (NotFoundException $e) {
145
-			return false;
146
-		}
147
-	}
148
-
149
-	/**
150
-	 * @param string $path
151
-	 * @return \OC\Files\Node\Folder
152
-	 * @throws \OCP\Files\NotPermittedException
153
-	 */
154
-	public function newFolder($path) {
155
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
156
-			$fullPath = $this->getFullPath($path);
157
-			$nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath);
158
-			$this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
159
-			$this->root->emit('\OC\Files', 'preCreate', array($nonExisting));
160
-			$this->view->mkdir($fullPath);
161
-			$node = new Folder($this->root, $this->view, $fullPath);
162
-			$this->root->emit('\OC\Files', 'postWrite', array($node));
163
-			$this->root->emit('\OC\Files', 'postCreate', array($node));
164
-			return $node;
165
-		} else {
166
-			throw new NotPermittedException('No create permission for folder');
167
-		}
168
-	}
169
-
170
-	/**
171
-	 * @param string $path
172
-	 * @return \OC\Files\Node\File
173
-	 * @throws \OCP\Files\NotPermittedException
174
-	 */
175
-	public function newFile($path) {
176
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
177
-			$fullPath = $this->getFullPath($path);
178
-			$nonExisting = new NonExistingFile($this->root, $this->view, $fullPath);
179
-			$this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
180
-			$this->root->emit('\OC\Files', 'preCreate', array($nonExisting));
181
-			$this->view->touch($fullPath);
182
-			$node = new File($this->root, $this->view, $fullPath);
183
-			$this->root->emit('\OC\Files', 'postWrite', array($node));
184
-			$this->root->emit('\OC\Files', 'postCreate', array($node));
185
-			return $node;
186
-		} else {
187
-			throw new NotPermittedException('No create permission for path');
188
-		}
189
-	}
190
-
191
-	/**
192
-	 * search for files with the name matching $query
193
-	 *
194
-	 * @param string|ISearchOperator $query
195
-	 * @return \OC\Files\Node\Node[]
196
-	 */
197
-	public function search($query) {
198
-		if (is_string($query)) {
199
-			return $this->searchCommon('search', array('%' . $query . '%'));
200
-		} else {
201
-			return $this->searchCommon('searchQuery', array($query));
202
-		}
203
-	}
204
-
205
-	/**
206
-	 * search for files by mimetype
207
-	 *
208
-	 * @param string $mimetype
209
-	 * @return Node[]
210
-	 */
211
-	public function searchByMime($mimetype) {
212
-		return $this->searchCommon('searchByMime', array($mimetype));
213
-	}
214
-
215
-	/**
216
-	 * search for files by tag
217
-	 *
218
-	 * @param string|int $tag name or tag id
219
-	 * @param string $userId owner of the tags
220
-	 * @return Node[]
221
-	 */
222
-	public function searchByTag($tag, $userId) {
223
-		return $this->searchCommon('searchByTag', array($tag, $userId));
224
-	}
225
-
226
-	/**
227
-	 * @param string $method cache method
228
-	 * @param array $args call args
229
-	 * @return \OC\Files\Node\Node[]
230
-	 */
231
-	private function searchCommon($method, $args) {
232
-		$files = array();
233
-		$rootLength = strlen($this->path);
234
-		$mount = $this->root->getMount($this->path);
235
-		$storage = $mount->getStorage();
236
-		$internalPath = $mount->getInternalPath($this->path);
237
-		$internalPath = rtrim($internalPath, '/');
238
-		if ($internalPath !== '') {
239
-			$internalPath = $internalPath . '/';
240
-		}
241
-		$internalRootLength = strlen($internalPath);
242
-
243
-		$cache = $storage->getCache('');
244
-
245
-		$results = call_user_func_array(array($cache, $method), $args);
246
-		foreach ($results as $result) {
247
-			if ($internalRootLength === 0 or substr($result['path'], 0, $internalRootLength) === $internalPath) {
248
-				$result['internalPath'] = $result['path'];
249
-				$result['path'] = substr($result['path'], $internalRootLength);
250
-				$result['storage'] = $storage;
251
-				$files[] = new \OC\Files\FileInfo($this->path . '/' . $result['path'], $storage, $result['internalPath'], $result, $mount);
252
-			}
253
-		}
254
-
255
-		$mounts = $this->root->getMountsIn($this->path);
256
-		foreach ($mounts as $mount) {
257
-			$storage = $mount->getStorage();
258
-			if ($storage) {
259
-				$cache = $storage->getCache('');
260
-
261
-				$relativeMountPoint = substr($mount->getMountPoint(), $rootLength);
262
-				$results = call_user_func_array(array($cache, $method), $args);
263
-				foreach ($results as $result) {
264
-					$result['internalPath'] = $result['path'];
265
-					$result['path'] = $relativeMountPoint . $result['path'];
266
-					$result['storage'] = $storage;
267
-					$files[] = new \OC\Files\FileInfo($this->path . '/' . $result['path'], $storage, $result['internalPath'], $result, $mount);
268
-				}
269
-			}
270
-		}
271
-
272
-		return array_map(function (FileInfo $file) {
273
-			return $this->createNode($file->getPath(), $file);
274
-		}, $files);
275
-	}
276
-
277
-	/**
278
-	 * @param int $id
279
-	 * @return \OC\Files\Node\Node[]
280
-	 */
281
-	public function getById($id) {
282
-		$mountCache = $this->root->getUserMountCache();
283
-		if (strpos($this->getPath(), '/', 1) > 0) {
284
-			list(, $user) = explode('/', $this->getPath());
285
-		} else {
286
-			$user = null;
287
-		}
288
-		$mountsContainingFile = $mountCache->getMountsForFileId((int)$id, $user);
289
-		$mounts = $this->root->getMountsIn($this->path);
290
-		$mounts[] = $this->root->getMount($this->path);
291
-		/** @var IMountPoint[] $folderMounts */
292
-		$folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) {
293
-			return $mountPoint->getMountPoint();
294
-		}, $mounts), $mounts);
295
-
296
-		/** @var ICachedMountInfo[] $mountsContainingFile */
297
-		$mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
298
-			return isset($folderMounts[$cachedMountInfo->getMountPoint()]);
299
-		}));
300
-
301
-		if (count($mountsContainingFile) === 0) {
302
-			return [];
303
-		}
304
-
305
-		// we only need to get the cache info once, since all mounts we found point to the same storage
306
-
307
-		$mount = $folderMounts[$mountsContainingFile[0]->getMountPoint()];
308
-		$cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
309
-		if (!$cacheEntry) {
310
-			return [];
311
-		}
312
-		// cache jails will hide the "true" internal path
313
-		$internalPath = ltrim($mountsContainingFile[0]->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
314
-
315
-		$nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($cacheEntry, $folderMounts, $internalPath) {
316
-			$mount = $folderMounts[$cachedMountInfo->getMountPoint()];
317
-			$pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
318
-			$pathRelativeToMount = ltrim($pathRelativeToMount, '/');
319
-			$absolutePath = $cachedMountInfo->getMountPoint() . $pathRelativeToMount;
320
-			return $this->root->createNode($absolutePath, new \OC\Files\FileInfo(
321
-				$absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount,
322
-				\OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount))
323
-			));
324
-		}, $mountsContainingFile);
325
-
326
-		return array_filter($nodes, function (Node $node) {
327
-			return $this->getRelativePath($node->getPath());
328
-		});
329
-	}
330
-
331
-	public function getFreeSpace() {
332
-		return $this->view->free_space($this->path);
333
-	}
334
-
335
-	public function delete() {
336
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
337
-			$this->sendHooks(array('preDelete'));
338
-			$fileInfo = $this->getFileInfo();
339
-			$this->view->rmdir($this->path);
340
-			$nonExisting = new NonExistingFolder($this->root, $this->view, $this->path, $fileInfo);
341
-			$this->root->emit('\OC\Files', 'postDelete', array($nonExisting));
342
-			$this->exists = false;
343
-		} else {
344
-			throw new NotPermittedException('No delete permission for path');
345
-		}
346
-	}
347
-
348
-	/**
349
-	 * Add a suffix to the name in case the file exists
350
-	 *
351
-	 * @param string $name
352
-	 * @return string
353
-	 * @throws NotPermittedException
354
-	 */
355
-	public function getNonExistingName($name) {
356
-		$uniqueName = \OC_Helper::buildNotExistingFileNameForView($this->getPath(), $name, $this->view);
357
-		return trim($this->getRelativePath($uniqueName), '/');
358
-	}
359
-
360
-	/**
361
-	 * @param int $limit
362
-	 * @param int $offset
363
-	 * @return \OCP\Files\Node[]
364
-	 */
365
-	public function getRecent($limit, $offset = 0) {
366
-		$mimetypeLoader = \OC::$server->getMimeTypeLoader();
367
-		$mounts = $this->root->getMountsIn($this->path);
368
-		$mounts[] = $this->getMountPoint();
369
-
370
-		$mounts = array_filter($mounts, function (IMountPoint $mount) {
371
-			return $mount->getStorage();
372
-		});
373
-		$storageIds = array_map(function (IMountPoint $mount) {
374
-			return $mount->getStorage()->getCache()->getNumericStorageId();
375
-		}, $mounts);
376
-		/** @var IMountPoint[] $mountMap */
377
-		$mountMap = array_combine($storageIds, $mounts);
378
-		$folderMimetype = $mimetypeLoader->getId(FileInfo::MIMETYPE_FOLDER);
379
-
380
-		//todo look into options of filtering path based on storage id (only search in files/ for home storage, filter by share root for shared, etc)
381
-
382
-		$builder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
383
-		$query = $builder
384
-			->select('f.*')
385
-			->from('filecache', 'f')
386
-			->andWhere($builder->expr()->in('f.storage', $builder->createNamedParameter($storageIds, IQueryBuilder::PARAM_INT_ARRAY)))
387
-			->andWhere($builder->expr()->orX(
388
-			// handle non empty folders separate
389
-				$builder->expr()->neq('f.mimetype', $builder->createNamedParameter($folderMimetype, IQueryBuilder::PARAM_INT)),
390
-				$builder->expr()->eq('f.size', new Literal(0))
391
-			))
392
-			->orderBy('f.mtime', 'DESC')
393
-			->setMaxResults($limit)
394
-			->setFirstResult($offset);
395
-
396
-		$result = $query->execute()->fetchAll();
397
-
398
-		$files = array_filter(array_map(function (array $entry) use ($mountMap, $mimetypeLoader) {
399
-			$mount = $mountMap[$entry['storage']];
400
-			$entry['internalPath'] = $entry['path'];
401
-			$entry['mimetype'] = $mimetypeLoader->getMimetypeById($entry['mimetype']);
402
-			$entry['mimepart'] = $mimetypeLoader->getMimetypeById($entry['mimepart']);
403
-			$path = $this->getAbsolutePath($mount, $entry['path']);
404
-			if (is_null($path)) {
405
-				return null;
406
-			}
407
-			$fileInfo = new \OC\Files\FileInfo($path, $mount->getStorage(), $entry['internalPath'], $entry, $mount);
408
-			return $this->root->createNode($fileInfo->getPath(), $fileInfo);
409
-		}, $result));
410
-
411
-		return array_values(array_filter($files, function (Node $node) {
412
-			$relative = $this->getRelativePath($node->getPath());
413
-			return $relative !== null && $relative !== '/';
414
-		}));
415
-	}
416
-
417
-	private function getAbsolutePath(IMountPoint $mount, $path) {
418
-		$storage = $mount->getStorage();
419
-		if ($storage->instanceOfStorage('\OC\Files\Storage\Wrapper\Jail')) {
420
-			/** @var \OC\Files\Storage\Wrapper\Jail $storage */
421
-			$jailRoot = $storage->getUnjailedPath('');
422
-			$rootLength = strlen($jailRoot) + 1;
423
-			if ($path === $jailRoot) {
424
-				return $mount->getMountPoint();
425
-			} else if (substr($path, 0, $rootLength) === $jailRoot . '/') {
426
-				return $mount->getMountPoint() . substr($path, $rootLength);
427
-			} else {
428
-				return null;
429
-			}
430
-		} else {
431
-			return $mount->getMountPoint() . $path;
432
-		}
433
-	}
39
+    /**
40
+     * Creates a Folder that represents a non-existing path
41
+     *
42
+     * @param string $path path
43
+     * @return string non-existing node class
44
+     */
45
+    protected function createNonExistingNode($path) {
46
+        return new NonExistingFolder($this->root, $this->view, $path);
47
+    }
48
+
49
+    /**
50
+     * @param string $path path relative to the folder
51
+     * @return string
52
+     * @throws \OCP\Files\NotPermittedException
53
+     */
54
+    public function getFullPath($path) {
55
+        if (!$this->isValidPath($path)) {
56
+            throw new NotPermittedException('Invalid path');
57
+        }
58
+        return $this->path . $this->normalizePath($path);
59
+    }
60
+
61
+    /**
62
+     * @param string $path
63
+     * @return string
64
+     */
65
+    public function getRelativePath($path) {
66
+        if ($this->path === '' or $this->path === '/') {
67
+            return $this->normalizePath($path);
68
+        }
69
+        if ($path === $this->path) {
70
+            return '/';
71
+        } else if (strpos($path, $this->path . '/') !== 0) {
72
+            return null;
73
+        } else {
74
+            $path = substr($path, strlen($this->path));
75
+            return $this->normalizePath($path);
76
+        }
77
+    }
78
+
79
+    /**
80
+     * check if a node is a (grand-)child of the folder
81
+     *
82
+     * @param \OC\Files\Node\Node $node
83
+     * @return bool
84
+     */
85
+    public function isSubNode($node) {
86
+        return strpos($node->getPath(), $this->path . '/') === 0;
87
+    }
88
+
89
+    /**
90
+     * get the content of this directory
91
+     *
92
+     * @throws \OCP\Files\NotFoundException
93
+     * @return Node[]
94
+     */
95
+    public function getDirectoryListing() {
96
+        $folderContent = $this->view->getDirectoryContent($this->path);
97
+
98
+        return array_map(function (FileInfo $info) {
99
+            if ($info->getMimetype() === 'httpd/unix-directory') {
100
+                return new Folder($this->root, $this->view, $info->getPath(), $info);
101
+            } else {
102
+                return new File($this->root, $this->view, $info->getPath(), $info);
103
+            }
104
+        }, $folderContent);
105
+    }
106
+
107
+    /**
108
+     * @param string $path
109
+     * @param FileInfo $info
110
+     * @return File|Folder
111
+     */
112
+    protected function createNode($path, FileInfo $info = null) {
113
+        if (is_null($info)) {
114
+            $isDir = $this->view->is_dir($path);
115
+        } else {
116
+            $isDir = $info->getType() === FileInfo::TYPE_FOLDER;
117
+        }
118
+        if ($isDir) {
119
+            return new Folder($this->root, $this->view, $path, $info);
120
+        } else {
121
+            return new File($this->root, $this->view, $path, $info);
122
+        }
123
+    }
124
+
125
+    /**
126
+     * Get the node at $path
127
+     *
128
+     * @param string $path
129
+     * @return \OC\Files\Node\Node
130
+     * @throws \OCP\Files\NotFoundException
131
+     */
132
+    public function get($path) {
133
+        return $this->root->get($this->getFullPath($path));
134
+    }
135
+
136
+    /**
137
+     * @param string $path
138
+     * @return bool
139
+     */
140
+    public function nodeExists($path) {
141
+        try {
142
+            $this->get($path);
143
+            return true;
144
+        } catch (NotFoundException $e) {
145
+            return false;
146
+        }
147
+    }
148
+
149
+    /**
150
+     * @param string $path
151
+     * @return \OC\Files\Node\Folder
152
+     * @throws \OCP\Files\NotPermittedException
153
+     */
154
+    public function newFolder($path) {
155
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
156
+            $fullPath = $this->getFullPath($path);
157
+            $nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath);
158
+            $this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
159
+            $this->root->emit('\OC\Files', 'preCreate', array($nonExisting));
160
+            $this->view->mkdir($fullPath);
161
+            $node = new Folder($this->root, $this->view, $fullPath);
162
+            $this->root->emit('\OC\Files', 'postWrite', array($node));
163
+            $this->root->emit('\OC\Files', 'postCreate', array($node));
164
+            return $node;
165
+        } else {
166
+            throw new NotPermittedException('No create permission for folder');
167
+        }
168
+    }
169
+
170
+    /**
171
+     * @param string $path
172
+     * @return \OC\Files\Node\File
173
+     * @throws \OCP\Files\NotPermittedException
174
+     */
175
+    public function newFile($path) {
176
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
177
+            $fullPath = $this->getFullPath($path);
178
+            $nonExisting = new NonExistingFile($this->root, $this->view, $fullPath);
179
+            $this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
180
+            $this->root->emit('\OC\Files', 'preCreate', array($nonExisting));
181
+            $this->view->touch($fullPath);
182
+            $node = new File($this->root, $this->view, $fullPath);
183
+            $this->root->emit('\OC\Files', 'postWrite', array($node));
184
+            $this->root->emit('\OC\Files', 'postCreate', array($node));
185
+            return $node;
186
+        } else {
187
+            throw new NotPermittedException('No create permission for path');
188
+        }
189
+    }
190
+
191
+    /**
192
+     * search for files with the name matching $query
193
+     *
194
+     * @param string|ISearchOperator $query
195
+     * @return \OC\Files\Node\Node[]
196
+     */
197
+    public function search($query) {
198
+        if (is_string($query)) {
199
+            return $this->searchCommon('search', array('%' . $query . '%'));
200
+        } else {
201
+            return $this->searchCommon('searchQuery', array($query));
202
+        }
203
+    }
204
+
205
+    /**
206
+     * search for files by mimetype
207
+     *
208
+     * @param string $mimetype
209
+     * @return Node[]
210
+     */
211
+    public function searchByMime($mimetype) {
212
+        return $this->searchCommon('searchByMime', array($mimetype));
213
+    }
214
+
215
+    /**
216
+     * search for files by tag
217
+     *
218
+     * @param string|int $tag name or tag id
219
+     * @param string $userId owner of the tags
220
+     * @return Node[]
221
+     */
222
+    public function searchByTag($tag, $userId) {
223
+        return $this->searchCommon('searchByTag', array($tag, $userId));
224
+    }
225
+
226
+    /**
227
+     * @param string $method cache method
228
+     * @param array $args call args
229
+     * @return \OC\Files\Node\Node[]
230
+     */
231
+    private function searchCommon($method, $args) {
232
+        $files = array();
233
+        $rootLength = strlen($this->path);
234
+        $mount = $this->root->getMount($this->path);
235
+        $storage = $mount->getStorage();
236
+        $internalPath = $mount->getInternalPath($this->path);
237
+        $internalPath = rtrim($internalPath, '/');
238
+        if ($internalPath !== '') {
239
+            $internalPath = $internalPath . '/';
240
+        }
241
+        $internalRootLength = strlen($internalPath);
242
+
243
+        $cache = $storage->getCache('');
244
+
245
+        $results = call_user_func_array(array($cache, $method), $args);
246
+        foreach ($results as $result) {
247
+            if ($internalRootLength === 0 or substr($result['path'], 0, $internalRootLength) === $internalPath) {
248
+                $result['internalPath'] = $result['path'];
249
+                $result['path'] = substr($result['path'], $internalRootLength);
250
+                $result['storage'] = $storage;
251
+                $files[] = new \OC\Files\FileInfo($this->path . '/' . $result['path'], $storage, $result['internalPath'], $result, $mount);
252
+            }
253
+        }
254
+
255
+        $mounts = $this->root->getMountsIn($this->path);
256
+        foreach ($mounts as $mount) {
257
+            $storage = $mount->getStorage();
258
+            if ($storage) {
259
+                $cache = $storage->getCache('');
260
+
261
+                $relativeMountPoint = substr($mount->getMountPoint(), $rootLength);
262
+                $results = call_user_func_array(array($cache, $method), $args);
263
+                foreach ($results as $result) {
264
+                    $result['internalPath'] = $result['path'];
265
+                    $result['path'] = $relativeMountPoint . $result['path'];
266
+                    $result['storage'] = $storage;
267
+                    $files[] = new \OC\Files\FileInfo($this->path . '/' . $result['path'], $storage, $result['internalPath'], $result, $mount);
268
+                }
269
+            }
270
+        }
271
+
272
+        return array_map(function (FileInfo $file) {
273
+            return $this->createNode($file->getPath(), $file);
274
+        }, $files);
275
+    }
276
+
277
+    /**
278
+     * @param int $id
279
+     * @return \OC\Files\Node\Node[]
280
+     */
281
+    public function getById($id) {
282
+        $mountCache = $this->root->getUserMountCache();
283
+        if (strpos($this->getPath(), '/', 1) > 0) {
284
+            list(, $user) = explode('/', $this->getPath());
285
+        } else {
286
+            $user = null;
287
+        }
288
+        $mountsContainingFile = $mountCache->getMountsForFileId((int)$id, $user);
289
+        $mounts = $this->root->getMountsIn($this->path);
290
+        $mounts[] = $this->root->getMount($this->path);
291
+        /** @var IMountPoint[] $folderMounts */
292
+        $folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) {
293
+            return $mountPoint->getMountPoint();
294
+        }, $mounts), $mounts);
295
+
296
+        /** @var ICachedMountInfo[] $mountsContainingFile */
297
+        $mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
298
+            return isset($folderMounts[$cachedMountInfo->getMountPoint()]);
299
+        }));
300
+
301
+        if (count($mountsContainingFile) === 0) {
302
+            return [];
303
+        }
304
+
305
+        // we only need to get the cache info once, since all mounts we found point to the same storage
306
+
307
+        $mount = $folderMounts[$mountsContainingFile[0]->getMountPoint()];
308
+        $cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
309
+        if (!$cacheEntry) {
310
+            return [];
311
+        }
312
+        // cache jails will hide the "true" internal path
313
+        $internalPath = ltrim($mountsContainingFile[0]->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
314
+
315
+        $nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($cacheEntry, $folderMounts, $internalPath) {
316
+            $mount = $folderMounts[$cachedMountInfo->getMountPoint()];
317
+            $pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
318
+            $pathRelativeToMount = ltrim($pathRelativeToMount, '/');
319
+            $absolutePath = $cachedMountInfo->getMountPoint() . $pathRelativeToMount;
320
+            return $this->root->createNode($absolutePath, new \OC\Files\FileInfo(
321
+                $absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount,
322
+                \OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount))
323
+            ));
324
+        }, $mountsContainingFile);
325
+
326
+        return array_filter($nodes, function (Node $node) {
327
+            return $this->getRelativePath($node->getPath());
328
+        });
329
+    }
330
+
331
+    public function getFreeSpace() {
332
+        return $this->view->free_space($this->path);
333
+    }
334
+
335
+    public function delete() {
336
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
337
+            $this->sendHooks(array('preDelete'));
338
+            $fileInfo = $this->getFileInfo();
339
+            $this->view->rmdir($this->path);
340
+            $nonExisting = new NonExistingFolder($this->root, $this->view, $this->path, $fileInfo);
341
+            $this->root->emit('\OC\Files', 'postDelete', array($nonExisting));
342
+            $this->exists = false;
343
+        } else {
344
+            throw new NotPermittedException('No delete permission for path');
345
+        }
346
+    }
347
+
348
+    /**
349
+     * Add a suffix to the name in case the file exists
350
+     *
351
+     * @param string $name
352
+     * @return string
353
+     * @throws NotPermittedException
354
+     */
355
+    public function getNonExistingName($name) {
356
+        $uniqueName = \OC_Helper::buildNotExistingFileNameForView($this->getPath(), $name, $this->view);
357
+        return trim($this->getRelativePath($uniqueName), '/');
358
+    }
359
+
360
+    /**
361
+     * @param int $limit
362
+     * @param int $offset
363
+     * @return \OCP\Files\Node[]
364
+     */
365
+    public function getRecent($limit, $offset = 0) {
366
+        $mimetypeLoader = \OC::$server->getMimeTypeLoader();
367
+        $mounts = $this->root->getMountsIn($this->path);
368
+        $mounts[] = $this->getMountPoint();
369
+
370
+        $mounts = array_filter($mounts, function (IMountPoint $mount) {
371
+            return $mount->getStorage();
372
+        });
373
+        $storageIds = array_map(function (IMountPoint $mount) {
374
+            return $mount->getStorage()->getCache()->getNumericStorageId();
375
+        }, $mounts);
376
+        /** @var IMountPoint[] $mountMap */
377
+        $mountMap = array_combine($storageIds, $mounts);
378
+        $folderMimetype = $mimetypeLoader->getId(FileInfo::MIMETYPE_FOLDER);
379
+
380
+        //todo look into options of filtering path based on storage id (only search in files/ for home storage, filter by share root for shared, etc)
381
+
382
+        $builder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
383
+        $query = $builder
384
+            ->select('f.*')
385
+            ->from('filecache', 'f')
386
+            ->andWhere($builder->expr()->in('f.storage', $builder->createNamedParameter($storageIds, IQueryBuilder::PARAM_INT_ARRAY)))
387
+            ->andWhere($builder->expr()->orX(
388
+            // handle non empty folders separate
389
+                $builder->expr()->neq('f.mimetype', $builder->createNamedParameter($folderMimetype, IQueryBuilder::PARAM_INT)),
390
+                $builder->expr()->eq('f.size', new Literal(0))
391
+            ))
392
+            ->orderBy('f.mtime', 'DESC')
393
+            ->setMaxResults($limit)
394
+            ->setFirstResult($offset);
395
+
396
+        $result = $query->execute()->fetchAll();
397
+
398
+        $files = array_filter(array_map(function (array $entry) use ($mountMap, $mimetypeLoader) {
399
+            $mount = $mountMap[$entry['storage']];
400
+            $entry['internalPath'] = $entry['path'];
401
+            $entry['mimetype'] = $mimetypeLoader->getMimetypeById($entry['mimetype']);
402
+            $entry['mimepart'] = $mimetypeLoader->getMimetypeById($entry['mimepart']);
403
+            $path = $this->getAbsolutePath($mount, $entry['path']);
404
+            if (is_null($path)) {
405
+                return null;
406
+            }
407
+            $fileInfo = new \OC\Files\FileInfo($path, $mount->getStorage(), $entry['internalPath'], $entry, $mount);
408
+            return $this->root->createNode($fileInfo->getPath(), $fileInfo);
409
+        }, $result));
410
+
411
+        return array_values(array_filter($files, function (Node $node) {
412
+            $relative = $this->getRelativePath($node->getPath());
413
+            return $relative !== null && $relative !== '/';
414
+        }));
415
+    }
416
+
417
+    private function getAbsolutePath(IMountPoint $mount, $path) {
418
+        $storage = $mount->getStorage();
419
+        if ($storage->instanceOfStorage('\OC\Files\Storage\Wrapper\Jail')) {
420
+            /** @var \OC\Files\Storage\Wrapper\Jail $storage */
421
+            $jailRoot = $storage->getUnjailedPath('');
422
+            $rootLength = strlen($jailRoot) + 1;
423
+            if ($path === $jailRoot) {
424
+                return $mount->getMountPoint();
425
+            } else if (substr($path, 0, $rootLength) === $jailRoot . '/') {
426
+                return $mount->getMountPoint() . substr($path, $rootLength);
427
+            } else {
428
+                return null;
429
+            }
430
+        } else {
431
+            return $mount->getMountPoint() . $path;
432
+        }
433
+    }
434 434
 }
Please login to merge, or discard this patch.
Spacing   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -55,7 +55,7 @@  discard block
 block discarded – undo
55 55
 		if (!$this->isValidPath($path)) {
56 56
 			throw new NotPermittedException('Invalid path');
57 57
 		}
58
-		return $this->path . $this->normalizePath($path);
58
+		return $this->path.$this->normalizePath($path);
59 59
 	}
60 60
 
61 61
 	/**
@@ -68,7 +68,7 @@  discard block
 block discarded – undo
68 68
 		}
69 69
 		if ($path === $this->path) {
70 70
 			return '/';
71
-		} else if (strpos($path, $this->path . '/') !== 0) {
71
+		} else if (strpos($path, $this->path.'/') !== 0) {
72 72
 			return null;
73 73
 		} else {
74 74
 			$path = substr($path, strlen($this->path));
@@ -83,7 +83,7 @@  discard block
 block discarded – undo
83 83
 	 * @return bool
84 84
 	 */
85 85
 	public function isSubNode($node) {
86
-		return strpos($node->getPath(), $this->path . '/') === 0;
86
+		return strpos($node->getPath(), $this->path.'/') === 0;
87 87
 	}
88 88
 
89 89
 	/**
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
 	public function getDirectoryListing() {
96 96
 		$folderContent = $this->view->getDirectoryContent($this->path);
97 97
 
98
-		return array_map(function (FileInfo $info) {
98
+		return array_map(function(FileInfo $info) {
99 99
 			if ($info->getMimetype() === 'httpd/unix-directory') {
100 100
 				return new Folder($this->root, $this->view, $info->getPath(), $info);
101 101
 			} else {
@@ -196,7 +196,7 @@  discard block
 block discarded – undo
196 196
 	 */
197 197
 	public function search($query) {
198 198
 		if (is_string($query)) {
199
-			return $this->searchCommon('search', array('%' . $query . '%'));
199
+			return $this->searchCommon('search', array('%'.$query.'%'));
200 200
 		} else {
201 201
 			return $this->searchCommon('searchQuery', array($query));
202 202
 		}
@@ -236,7 +236,7 @@  discard block
 block discarded – undo
236 236
 		$internalPath = $mount->getInternalPath($this->path);
237 237
 		$internalPath = rtrim($internalPath, '/');
238 238
 		if ($internalPath !== '') {
239
-			$internalPath = $internalPath . '/';
239
+			$internalPath = $internalPath.'/';
240 240
 		}
241 241
 		$internalRootLength = strlen($internalPath);
242 242
 
@@ -248,7 +248,7 @@  discard block
 block discarded – undo
248 248
 				$result['internalPath'] = $result['path'];
249 249
 				$result['path'] = substr($result['path'], $internalRootLength);
250 250
 				$result['storage'] = $storage;
251
-				$files[] = new \OC\Files\FileInfo($this->path . '/' . $result['path'], $storage, $result['internalPath'], $result, $mount);
251
+				$files[] = new \OC\Files\FileInfo($this->path.'/'.$result['path'], $storage, $result['internalPath'], $result, $mount);
252 252
 			}
253 253
 		}
254 254
 
@@ -262,14 +262,14 @@  discard block
 block discarded – undo
262 262
 				$results = call_user_func_array(array($cache, $method), $args);
263 263
 				foreach ($results as $result) {
264 264
 					$result['internalPath'] = $result['path'];
265
-					$result['path'] = $relativeMountPoint . $result['path'];
265
+					$result['path'] = $relativeMountPoint.$result['path'];
266 266
 					$result['storage'] = $storage;
267
-					$files[] = new \OC\Files\FileInfo($this->path . '/' . $result['path'], $storage, $result['internalPath'], $result, $mount);
267
+					$files[] = new \OC\Files\FileInfo($this->path.'/'.$result['path'], $storage, $result['internalPath'], $result, $mount);
268 268
 				}
269 269
 			}
270 270
 		}
271 271
 
272
-		return array_map(function (FileInfo $file) {
272
+		return array_map(function(FileInfo $file) {
273 273
 			return $this->createNode($file->getPath(), $file);
274 274
 		}, $files);
275 275
 	}
@@ -285,16 +285,16 @@  discard block
 block discarded – undo
285 285
 		} else {
286 286
 			$user = null;
287 287
 		}
288
-		$mountsContainingFile = $mountCache->getMountsForFileId((int)$id, $user);
288
+		$mountsContainingFile = $mountCache->getMountsForFileId((int) $id, $user);
289 289
 		$mounts = $this->root->getMountsIn($this->path);
290 290
 		$mounts[] = $this->root->getMount($this->path);
291 291
 		/** @var IMountPoint[] $folderMounts */
292
-		$folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) {
292
+		$folderMounts = array_combine(array_map(function(IMountPoint $mountPoint) {
293 293
 			return $mountPoint->getMountPoint();
294 294
 		}, $mounts), $mounts);
295 295
 
296 296
 		/** @var ICachedMountInfo[] $mountsContainingFile */
297
-		$mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
297
+		$mountsContainingFile = array_values(array_filter($mountsContainingFile, function(ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
298 298
 			return isset($folderMounts[$cachedMountInfo->getMountPoint()]);
299 299
 		}));
300 300
 
@@ -305,25 +305,25 @@  discard block
 block discarded – undo
305 305
 		// we only need to get the cache info once, since all mounts we found point to the same storage
306 306
 
307 307
 		$mount = $folderMounts[$mountsContainingFile[0]->getMountPoint()];
308
-		$cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
308
+		$cacheEntry = $mount->getStorage()->getCache()->get((int) $id);
309 309
 		if (!$cacheEntry) {
310 310
 			return [];
311 311
 		}
312 312
 		// cache jails will hide the "true" internal path
313
-		$internalPath = ltrim($mountsContainingFile[0]->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
313
+		$internalPath = ltrim($mountsContainingFile[0]->getRootInternalPath().'/'.$cacheEntry->getPath(), '/');
314 314
 
315
-		$nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($cacheEntry, $folderMounts, $internalPath) {
315
+		$nodes = array_map(function(ICachedMountInfo $cachedMountInfo) use ($cacheEntry, $folderMounts, $internalPath) {
316 316
 			$mount = $folderMounts[$cachedMountInfo->getMountPoint()];
317 317
 			$pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
318 318
 			$pathRelativeToMount = ltrim($pathRelativeToMount, '/');
319
-			$absolutePath = $cachedMountInfo->getMountPoint() . $pathRelativeToMount;
319
+			$absolutePath = $cachedMountInfo->getMountPoint().$pathRelativeToMount;
320 320
 			return $this->root->createNode($absolutePath, new \OC\Files\FileInfo(
321 321
 				$absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount,
322 322
 				\OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount))
323 323
 			));
324 324
 		}, $mountsContainingFile);
325 325
 
326
-		return array_filter($nodes, function (Node $node) {
326
+		return array_filter($nodes, function(Node $node) {
327 327
 			return $this->getRelativePath($node->getPath());
328 328
 		});
329 329
 	}
@@ -367,10 +367,10 @@  discard block
 block discarded – undo
367 367
 		$mounts = $this->root->getMountsIn($this->path);
368 368
 		$mounts[] = $this->getMountPoint();
369 369
 
370
-		$mounts = array_filter($mounts, function (IMountPoint $mount) {
370
+		$mounts = array_filter($mounts, function(IMountPoint $mount) {
371 371
 			return $mount->getStorage();
372 372
 		});
373
-		$storageIds = array_map(function (IMountPoint $mount) {
373
+		$storageIds = array_map(function(IMountPoint $mount) {
374 374
 			return $mount->getStorage()->getCache()->getNumericStorageId();
375 375
 		}, $mounts);
376 376
 		/** @var IMountPoint[] $mountMap */
@@ -395,7 +395,7 @@  discard block
 block discarded – undo
395 395
 
396 396
 		$result = $query->execute()->fetchAll();
397 397
 
398
-		$files = array_filter(array_map(function (array $entry) use ($mountMap, $mimetypeLoader) {
398
+		$files = array_filter(array_map(function(array $entry) use ($mountMap, $mimetypeLoader) {
399 399
 			$mount = $mountMap[$entry['storage']];
400 400
 			$entry['internalPath'] = $entry['path'];
401 401
 			$entry['mimetype'] = $mimetypeLoader->getMimetypeById($entry['mimetype']);
@@ -408,7 +408,7 @@  discard block
 block discarded – undo
408 408
 			return $this->root->createNode($fileInfo->getPath(), $fileInfo);
409 409
 		}, $result));
410 410
 
411
-		return array_values(array_filter($files, function (Node $node) {
411
+		return array_values(array_filter($files, function(Node $node) {
412 412
 			$relative = $this->getRelativePath($node->getPath());
413 413
 			return $relative !== null && $relative !== '/';
414 414
 		}));
@@ -422,13 +422,13 @@  discard block
 block discarded – undo
422 422
 			$rootLength = strlen($jailRoot) + 1;
423 423
 			if ($path === $jailRoot) {
424 424
 				return $mount->getMountPoint();
425
-			} else if (substr($path, 0, $rootLength) === $jailRoot . '/') {
426
-				return $mount->getMountPoint() . substr($path, $rootLength);
425
+			} else if (substr($path, 0, $rootLength) === $jailRoot.'/') {
426
+				return $mount->getMountPoint().substr($path, $rootLength);
427 427
 			} else {
428 428
 				return null;
429 429
 			}
430 430
 		} else {
431
-			return $mount->getMountPoint() . $path;
431
+			return $mount->getMountPoint().$path;
432 432
 		}
433 433
 	}
434 434
 }
Please login to merge, or discard this patch.
lib/public/Settings/IIconSection.php 2 patches
Doc Comments   +1 added lines patch added patch discarded remove patch
@@ -33,6 +33,7 @@
 block discarded – undo
33 33
 	 *
34 34
 	 * @returns string
35 35
 	 * @since 12
36
+	 * @return string
36 37
 	 */
37 38
 	public function getIcon();
38 39
 }
Please login to merge, or discard this patch.
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -27,12 +27,12 @@
 block discarded – undo
27 27
  * @since 12
28 28
  */
29 29
 interface IIconSection extends ISection {
30
-	/**
31
-	 * returns the relative path to an 16*16 icon describing the section.
32
-	 * e.g. '/core/img/places/files.svg'
33
-	 *
34
-	 * @returns string
35
-	 * @since 12
36
-	 */
37
-	public function getIcon();
30
+    /**
31
+     * returns the relative path to an 16*16 icon describing the section.
32
+     * e.g. '/core/img/places/files.svg'
33
+     *
34
+     * @returns string
35
+     * @since 12
36
+     */
37
+    public function getIcon();
38 38
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Lib/Storage/FTP.php 4 patches
Doc Comments   +3 added lines patch added patch discarded remove patch
@@ -139,6 +139,9 @@
 block discarded – undo
139 139
 		return false;
140 140
 	}
141 141
 
142
+	/**
143
+	 * @param string $path
144
+	 */
142 145
 	public function writeBack($tmpFile, $path) {
143 146
 		$this->uploadFile($tmpFile, $path);
144 147
 		unlink($tmpFile);
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -93,8 +93,7 @@
 block discarded – undo
93 93
 	public function unlink($path) {
94 94
 		if ($this->is_dir($path)) {
95 95
 			return $this->rmdir($path);
96
-		}
97
-		else {
96
+		} else {
98 97
 			$url = $this->constructUrl($path);
99 98
 			$result = unlink($url);
100 99
 			clearstatcache(true, $url);
Please login to merge, or discard this patch.
Indentation   +109 added lines, -109 removed lines patch added patch discarded remove patch
@@ -37,122 +37,122 @@
 block discarded – undo
37 37
 use Icewind\Streams\RetryWrapper;
38 38
 
39 39
 class FTP extends StreamWrapper{
40
-	private $password;
41
-	private $user;
42
-	private $host;
43
-	private $secure;
44
-	private $root;
40
+    private $password;
41
+    private $user;
42
+    private $host;
43
+    private $secure;
44
+    private $root;
45 45
 
46
-	private static $tempFiles=array();
46
+    private static $tempFiles=array();
47 47
 
48
-	public function __construct($params) {
49
-		if (isset($params['host']) && isset($params['user']) && isset($params['password'])) {
50
-			$this->host=$params['host'];
51
-			$this->user=$params['user'];
52
-			$this->password=$params['password'];
53
-			if (isset($params['secure'])) {
54
-				$this->secure = $params['secure'];
55
-			} else {
56
-				$this->secure = false;
57
-			}
58
-			$this->root=isset($params['root'])?$params['root']:'/';
59
-			if ( ! $this->root || $this->root[0]!=='/') {
60
-				$this->root='/'.$this->root;
61
-			}
62
-			if (substr($this->root, -1) !== '/') {
63
-				$this->root .= '/';
64
-			}
65
-		} else {
66
-			throw new \Exception('Creating FTP storage failed');
67
-		}
48
+    public function __construct($params) {
49
+        if (isset($params['host']) && isset($params['user']) && isset($params['password'])) {
50
+            $this->host=$params['host'];
51
+            $this->user=$params['user'];
52
+            $this->password=$params['password'];
53
+            if (isset($params['secure'])) {
54
+                $this->secure = $params['secure'];
55
+            } else {
56
+                $this->secure = false;
57
+            }
58
+            $this->root=isset($params['root'])?$params['root']:'/';
59
+            if ( ! $this->root || $this->root[0]!=='/') {
60
+                $this->root='/'.$this->root;
61
+            }
62
+            if (substr($this->root, -1) !== '/') {
63
+                $this->root .= '/';
64
+            }
65
+        } else {
66
+            throw new \Exception('Creating FTP storage failed');
67
+        }
68 68
 		
69
-	}
69
+    }
70 70
 
71
-	public function getId(){
72
-		return 'ftp::' . $this->user . '@' . $this->host . '/' . $this->root;
73
-	}
71
+    public function getId(){
72
+        return 'ftp::' . $this->user . '@' . $this->host . '/' . $this->root;
73
+    }
74 74
 
75
-	/**
76
-	 * construct the ftp url
77
-	 * @param string $path
78
-	 * @return string
79
-	 */
80
-	public function constructUrl($path) {
81
-		$url='ftp';
82
-		if ($this->secure) {
83
-			$url.='s';
84
-		}
85
-		$url.='://'.urlencode($this->user).':'.urlencode($this->password).'@'.$this->host.$this->root.$path;
86
-		return $url;
87
-	}
75
+    /**
76
+     * construct the ftp url
77
+     * @param string $path
78
+     * @return string
79
+     */
80
+    public function constructUrl($path) {
81
+        $url='ftp';
82
+        if ($this->secure) {
83
+            $url.='s';
84
+        }
85
+        $url.='://'.urlencode($this->user).':'.urlencode($this->password).'@'.$this->host.$this->root.$path;
86
+        return $url;
87
+    }
88 88
 
89
-	/**
90
-	 * Unlinks file or directory
91
-	 * @param string $path
92
-	 */
93
-	public function unlink($path) {
94
-		if ($this->is_dir($path)) {
95
-			return $this->rmdir($path);
96
-		}
97
-		else {
98
-			$url = $this->constructUrl($path);
99
-			$result = unlink($url);
100
-			clearstatcache(true, $url);
101
-			return $result;
102
-		}
103
-	}
104
-	public function fopen($path,$mode) {
105
-		switch($mode) {
106
-			case 'r':
107
-			case 'rb':
108
-			case 'w':
109
-			case 'wb':
110
-			case 'a':
111
-			case 'ab':
112
-				//these are supported by the wrapper
113
-				$context = stream_context_create(array('ftp' => array('overwrite' => true)));
114
-				$handle = fopen($this->constructUrl($path), $mode, false, $context);
115
-				return RetryWrapper::wrap($handle);
116
-			case 'r+':
117
-			case 'w+':
118
-			case 'wb+':
119
-			case 'a+':
120
-			case 'x':
121
-			case 'x+':
122
-			case 'c':
123
-			case 'c+':
124
-				//emulate these
125
-				if (strrpos($path, '.')!==false) {
126
-					$ext=substr($path, strrpos($path, '.'));
127
-				} else {
128
-					$ext='';
129
-				}
130
-				$tmpFile=\OCP\Files::tmpFile($ext);
131
-				if ($this->file_exists($path)) {
132
-					$this->getFile($path, $tmpFile);
133
-				}
134
-				$handle = fopen($tmpFile, $mode);
135
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
136
-					$this->writeBack($tmpFile, $path);
137
-				});
138
-		}
139
-		return false;
140
-	}
89
+    /**
90
+     * Unlinks file or directory
91
+     * @param string $path
92
+     */
93
+    public function unlink($path) {
94
+        if ($this->is_dir($path)) {
95
+            return $this->rmdir($path);
96
+        }
97
+        else {
98
+            $url = $this->constructUrl($path);
99
+            $result = unlink($url);
100
+            clearstatcache(true, $url);
101
+            return $result;
102
+        }
103
+    }
104
+    public function fopen($path,$mode) {
105
+        switch($mode) {
106
+            case 'r':
107
+            case 'rb':
108
+            case 'w':
109
+            case 'wb':
110
+            case 'a':
111
+            case 'ab':
112
+                //these are supported by the wrapper
113
+                $context = stream_context_create(array('ftp' => array('overwrite' => true)));
114
+                $handle = fopen($this->constructUrl($path), $mode, false, $context);
115
+                return RetryWrapper::wrap($handle);
116
+            case 'r+':
117
+            case 'w+':
118
+            case 'wb+':
119
+            case 'a+':
120
+            case 'x':
121
+            case 'x+':
122
+            case 'c':
123
+            case 'c+':
124
+                //emulate these
125
+                if (strrpos($path, '.')!==false) {
126
+                    $ext=substr($path, strrpos($path, '.'));
127
+                } else {
128
+                    $ext='';
129
+                }
130
+                $tmpFile=\OCP\Files::tmpFile($ext);
131
+                if ($this->file_exists($path)) {
132
+                    $this->getFile($path, $tmpFile);
133
+                }
134
+                $handle = fopen($tmpFile, $mode);
135
+                return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
136
+                    $this->writeBack($tmpFile, $path);
137
+                });
138
+        }
139
+        return false;
140
+    }
141 141
 
142
-	public function writeBack($tmpFile, $path) {
143
-		$this->uploadFile($tmpFile, $path);
144
-		unlink($tmpFile);
145
-	}
142
+    public function writeBack($tmpFile, $path) {
143
+        $this->uploadFile($tmpFile, $path);
144
+        unlink($tmpFile);
145
+    }
146 146
 
147
-	/**
148
-	 * check if php-ftp is installed
149
-	 */
150
-	public static function checkDependencies() {
151
-		if (function_exists('ftp_login')) {
152
-			return(true);
153
-		} else {
154
-			return array('ftp');
155
-		}
156
-	}
147
+    /**
148
+     * check if php-ftp is installed
149
+     */
150
+    public static function checkDependencies() {
151
+        if (function_exists('ftp_login')) {
152
+            return(true);
153
+        } else {
154
+            return array('ftp');
155
+        }
156
+    }
157 157
 
158 158
 }
Please login to merge, or discard this patch.
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -36,28 +36,28 @@  discard block
 block discarded – undo
36 36
 use Icewind\Streams\CallbackWrapper;
37 37
 use Icewind\Streams\RetryWrapper;
38 38
 
39
-class FTP extends StreamWrapper{
39
+class FTP extends StreamWrapper {
40 40
 	private $password;
41 41
 	private $user;
42 42
 	private $host;
43 43
 	private $secure;
44 44
 	private $root;
45 45
 
46
-	private static $tempFiles=array();
46
+	private static $tempFiles = array();
47 47
 
48 48
 	public function __construct($params) {
49 49
 		if (isset($params['host']) && isset($params['user']) && isset($params['password'])) {
50
-			$this->host=$params['host'];
51
-			$this->user=$params['user'];
52
-			$this->password=$params['password'];
50
+			$this->host = $params['host'];
51
+			$this->user = $params['user'];
52
+			$this->password = $params['password'];
53 53
 			if (isset($params['secure'])) {
54 54
 				$this->secure = $params['secure'];
55 55
 			} else {
56 56
 				$this->secure = false;
57 57
 			}
58
-			$this->root=isset($params['root'])?$params['root']:'/';
59
-			if ( ! $this->root || $this->root[0]!=='/') {
60
-				$this->root='/'.$this->root;
58
+			$this->root = isset($params['root']) ? $params['root'] : '/';
59
+			if (!$this->root || $this->root[0] !== '/') {
60
+				$this->root = '/'.$this->root;
61 61
 			}
62 62
 			if (substr($this->root, -1) !== '/') {
63 63
 				$this->root .= '/';
@@ -68,8 +68,8 @@  discard block
 block discarded – undo
68 68
 		
69 69
 	}
70 70
 
71
-	public function getId(){
72
-		return 'ftp::' . $this->user . '@' . $this->host . '/' . $this->root;
71
+	public function getId() {
72
+		return 'ftp::'.$this->user.'@'.$this->host.'/'.$this->root;
73 73
 	}
74 74
 
75 75
 	/**
@@ -78,11 +78,11 @@  discard block
 block discarded – undo
78 78
 	 * @return string
79 79
 	 */
80 80
 	public function constructUrl($path) {
81
-		$url='ftp';
81
+		$url = 'ftp';
82 82
 		if ($this->secure) {
83
-			$url.='s';
83
+			$url .= 's';
84 84
 		}
85
-		$url.='://'.urlencode($this->user).':'.urlencode($this->password).'@'.$this->host.$this->root.$path;
85
+		$url .= '://'.urlencode($this->user).':'.urlencode($this->password).'@'.$this->host.$this->root.$path;
86 86
 		return $url;
87 87
 	}
88 88
 
@@ -101,8 +101,8 @@  discard block
 block discarded – undo
101 101
 			return $result;
102 102
 		}
103 103
 	}
104
-	public function fopen($path,$mode) {
105
-		switch($mode) {
104
+	public function fopen($path, $mode) {
105
+		switch ($mode) {
106 106
 			case 'r':
107 107
 			case 'rb':
108 108
 			case 'w':
@@ -122,17 +122,17 @@  discard block
 block discarded – undo
122 122
 			case 'c':
123 123
 			case 'c+':
124 124
 				//emulate these
125
-				if (strrpos($path, '.')!==false) {
126
-					$ext=substr($path, strrpos($path, '.'));
125
+				if (strrpos($path, '.') !== false) {
126
+					$ext = substr($path, strrpos($path, '.'));
127 127
 				} else {
128
-					$ext='';
128
+					$ext = '';
129 129
 				}
130
-				$tmpFile=\OCP\Files::tmpFile($ext);
130
+				$tmpFile = \OCP\Files::tmpFile($ext);
131 131
 				if ($this->file_exists($path)) {
132 132
 					$this->getFile($path, $tmpFile);
133 133
 				}
134 134
 				$handle = fopen($tmpFile, $mode);
135
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
135
+				return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
136 136
 					$this->writeBack($tmpFile, $path);
137 137
 				});
138 138
 		}
Please login to merge, or discard this patch.
apps/files_external/lib/Lib/Storage/Swift.php 3 patches
Doc Comments   +3 added lines patch added patch discarded remove patch
@@ -616,6 +616,9 @@
 block discarded – undo
616 616
 		return $this->container;
617 617
 	}
618 618
 
619
+	/**
620
+	 * @param string $path
621
+	 */
619 622
 	public function writeBack($tmpFile, $path) {
620 623
 		$fileData = fopen($tmpFile, 'r');
621 624
 		$this->getContainer()->uploadObject($path, $fileData);
Please login to merge, or discard this patch.
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -163,7 +163,7 @@  discard block
 block discarded – undo
163 163
 			throw new \Exception("API Key or password, Username, Bucket and Region have to be configured.");
164 164
 		}
165 165
 
166
-		$this->id = 'swift::' . $params['user'] . md5($params['bucket']);
166
+		$this->id = 'swift::'.$params['user'].md5($params['bucket']);
167 167
 
168 168
 		$bucketUrl = Url::factory($params['bucket']);
169 169
 		if ($bucketUrl->isAbsolute()) {
@@ -236,16 +236,16 @@  discard block
 block discarded – undo
236 236
 				continue;
237 237
 			}
238 238
 
239
-			if ($this->is_dir($path . '/' . $file)) {
240
-				$this->rmdir($path . '/' . $file);
239
+			if ($this->is_dir($path.'/'.$file)) {
240
+				$this->rmdir($path.'/'.$file);
241 241
 			} else {
242
-				$this->unlink($path . '/' . $file);
242
+				$this->unlink($path.'/'.$file);
243 243
 			}
244 244
 		}
245 245
 
246 246
 		try {
247
-			$this->getContainer()->dataObject()->setName($path . '/')->delete();
248
-			$this->objectCache->remove($path . '/');
247
+			$this->getContainer()->dataObject()->setName($path.'/')->delete();
248
+			$this->objectCache->remove($path.'/');
249 249
 		} catch (Exceptions\DeleteError $e) {
250 250
 			\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
251 251
 			return false;
@@ -326,7 +326,7 @@  discard block
 block discarded – undo
326 326
 		}
327 327
 
328 328
 		$stat = array();
329
-		$stat['size'] = (int)$object->getContentLength();
329
+		$stat['size'] = (int) $object->getContentLength();
330 330
 		$stat['mtime'] = $mtime;
331 331
 		$stat['atime'] = time();
332 332
 		return $stat;
@@ -358,7 +358,7 @@  discard block
 block discarded – undo
358 358
 		try {
359 359
 			$this->getContainer()->dataObject()->setName($path)->delete();
360 360
 			$this->objectCache->remove($path);
361
-			$this->objectCache->remove($path . '/');
361
+			$this->objectCache->remove($path.'/');
362 362
 		} catch (ClientErrorResponseException $e) {
363 363
 			if ($e->getResponse()->getStatusCode() !== 404) {
364 364
 				\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
@@ -387,8 +387,8 @@  discard block
 block discarded – undo
387 387
 					$streamInterface = $streamFactory->fromRequest($client->get($c->getUrl($path)));
388 388
 					$streamInterface->rewind();
389 389
 					$stream = $streamInterface->getStream();
390
-					stream_context_set_option($stream, 'swift','content', $streamInterface);
391
-					if(!strrpos($streamInterface
390
+					stream_context_set_option($stream, 'swift', 'content', $streamInterface);
391
+					if (!strrpos($streamInterface
392 392
 						->getMetaData('wrapper_data')[0], '404 Not Found')) {
393 393
 						return $stream;
394 394
 					}
@@ -422,7 +422,7 @@  discard block
 block discarded – undo
422 422
 					file_put_contents($tmpFile, $source);
423 423
 				}
424 424
 				$handle = fopen($tmpFile, $mode);
425
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
425
+				return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
426 426
 					$this->writeBack($tmpFile, $path);
427 427
 				});
428 428
 		}
@@ -469,10 +469,10 @@  discard block
 block discarded – undo
469 469
 
470 470
 			try {
471 471
 				$source = $this->fetchObject($path1);
472
-				$source->copy($this->bucket . '/' . $path2);
472
+				$source->copy($this->bucket.'/'.$path2);
473 473
 				// invalidate target object to force repopulation on fetch
474 474
 				$this->objectCache->remove($path2);
475
-				$this->objectCache->remove($path2 . '/');
475
+				$this->objectCache->remove($path2.'/');
476 476
 			} catch (ClientErrorResponseException $e) {
477 477
 				\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
478 478
 				return false;
@@ -484,11 +484,11 @@  discard block
 block discarded – undo
484 484
 			$this->unlink($path2);
485 485
 
486 486
 			try {
487
-				$source = $this->fetchObject($path1 . '/');
488
-				$source->copy($this->bucket . '/' . $path2 . '/');
487
+				$source = $this->fetchObject($path1.'/');
488
+				$source->copy($this->bucket.'/'.$path2.'/');
489 489
 				// invalidate target object to force repopulation on fetch
490 490
 				$this->objectCache->remove($path2);
491
-				$this->objectCache->remove($path2 . '/');
491
+				$this->objectCache->remove($path2.'/');
492 492
 			} catch (ClientErrorResponseException $e) {
493 493
 				\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
494 494
 				return false;
@@ -500,8 +500,8 @@  discard block
 block discarded – undo
500 500
 					continue;
501 501
 				}
502 502
 
503
-				$source = $path1 . '/' . $file;
504
-				$target = $path2 . '/' . $file;
503
+				$source = $path1.'/'.$file;
504
+				$target = $path2.'/'.$file;
505 505
 				$this->copy($source, $target);
506 506
 			}
507 507
 
@@ -635,7 +635,7 @@  discard block
 block discarded – undo
635 635
 			$path = '';
636 636
 		}
637 637
 		$cachedContent = $this->getCache()->getFolderContents($path);
638
-		$cachedNames = array_map(function ($content) {
638
+		$cachedNames = array_map(function($content) {
639 639
 			return $content['name'];
640 640
 		}, $cachedContent);
641 641
 		sort($cachedNames);
Please login to merge, or discard this patch.
Indentation   +596 added lines, -596 removed lines patch added patch discarded remove patch
@@ -48,601 +48,601 @@
 block discarded – undo
48 48
 
49 49
 class Swift extends \OC\Files\Storage\Common {
50 50
 
51
-	/**
52
-	 * @var \OpenCloud\ObjectStore\Service
53
-	 */
54
-	private $connection;
55
-	/**
56
-	 * @var \OpenCloud\ObjectStore\Resource\Container
57
-	 */
58
-	private $container;
59
-	/**
60
-	 * @var \OpenCloud\OpenStack
61
-	 */
62
-	private $anchor;
63
-	/**
64
-	 * @var string
65
-	 */
66
-	private $bucket;
67
-	/**
68
-	 * Connection parameters
69
-	 *
70
-	 * @var array
71
-	 */
72
-	private $params;
73
-
74
-	/** @var string  */
75
-	private $id;
76
-
77
-	/**
78
-	 * Key value cache mapping path to data object. Maps path to
79
-	 * \OpenCloud\OpenStack\ObjectStorage\Resource\DataObject for existing
80
-	 * paths and path to false for not existing paths.
81
-	 * @var \OCP\ICache
82
-	 */
83
-	private $objectCache;
84
-
85
-	/**
86
-	 * @param string $path
87
-	 */
88
-	private function normalizePath($path) {
89
-		$path = trim($path, '/');
90
-
91
-		if (!$path) {
92
-			$path = '.';
93
-		}
94
-
95
-		$path = str_replace('#', '%23', $path);
96
-
97
-		return $path;
98
-	}
99
-
100
-	const SUBCONTAINER_FILE = '.subcontainers';
101
-
102
-	/**
103
-	 * translate directory path to container name
104
-	 *
105
-	 * @param string $path
106
-	 * @return string
107
-	 */
108
-
109
-	/**
110
-	 * Fetches an object from the API.
111
-	 * If the object is cached already or a
112
-	 * failed "doesn't exist" response was cached,
113
-	 * that one will be returned.
114
-	 *
115
-	 * @param string $path
116
-	 * @return \OpenCloud\ObjectStore\Resource\DataObject|bool object
117
-	 * or false if the object did not exist
118
-	 */
119
-	private function fetchObject($path) {
120
-		if ($this->objectCache->hasKey($path)) {
121
-			// might be "false" if object did not exist from last check
122
-			return $this->objectCache->get($path);
123
-		}
124
-		try {
125
-			$object = $this->getContainer()->getPartialObject($path);
126
-			$this->objectCache->set($path, $object);
127
-			return $object;
128
-		} catch (ClientErrorResponseException $e) {
129
-			// this exception happens when the object does not exist, which
130
-			// is expected in most cases
131
-			$this->objectCache->set($path, false);
132
-			return false;
133
-		} catch (ClientErrorResponseException $e) {
134
-			// Expected response is "404 Not Found", so only log if it isn't
135
-			if ($e->getResponse()->getStatusCode() !== 404) {
136
-				\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
137
-			}
138
-			return false;
139
-		}
140
-	}
141
-
142
-	/**
143
-	 * Returns whether the given path exists.
144
-	 *
145
-	 * @param string $path
146
-	 *
147
-	 * @return bool true if the object exist, false otherwise
148
-	 */
149
-	private function doesObjectExist($path) {
150
-		return $this->fetchObject($path) !== false;
151
-	}
152
-
153
-	public function __construct($params) {
154
-		if ((empty($params['key']) and empty($params['password']))
155
-			or empty($params['user']) or empty($params['bucket'])
156
-			or empty($params['region'])
157
-		) {
158
-			throw new \Exception("API Key or password, Username, Bucket and Region have to be configured.");
159
-		}
160
-
161
-		$this->id = 'swift::' . $params['user'] . md5($params['bucket']);
162
-
163
-		$bucketUrl = Url::factory($params['bucket']);
164
-		if ($bucketUrl->isAbsolute()) {
165
-			$this->bucket = end(($bucketUrl->getPathSegments()));
166
-			$params['endpoint_url'] = $bucketUrl->addPath('..')->normalizePath();
167
-		} else {
168
-			$this->bucket = $params['bucket'];
169
-		}
170
-
171
-		if (empty($params['url'])) {
172
-			$params['url'] = 'https://identity.api.rackspacecloud.com/v2.0/';
173
-		}
174
-
175
-		if (empty($params['service_name'])) {
176
-			$params['service_name'] = 'cloudFiles';
177
-		}
178
-
179
-		$this->params = $params;
180
-		// FIXME: private class...
181
-		$this->objectCache = new \OC\Cache\CappedMemoryCache();
182
-	}
183
-
184
-	public function mkdir($path) {
185
-		$path = $this->normalizePath($path);
186
-
187
-		if ($this->is_dir($path)) {
188
-			return false;
189
-		}
190
-
191
-		if ($path !== '.') {
192
-			$path .= '/';
193
-		}
194
-
195
-		try {
196
-			$customHeaders = array('content-type' => 'httpd/unix-directory');
197
-			$metadataHeaders = DataObject::stockHeaders(array());
198
-			$allHeaders = $customHeaders + $metadataHeaders;
199
-			$this->getContainer()->uploadObject($path, '', $allHeaders);
200
-			// invalidate so that the next access gets the real object
201
-			// with all properties
202
-			$this->objectCache->remove($path);
203
-		} catch (Exceptions\CreateUpdateError $e) {
204
-			\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
205
-			return false;
206
-		}
207
-
208
-		return true;
209
-	}
210
-
211
-	public function file_exists($path) {
212
-		$path = $this->normalizePath($path);
213
-
214
-		if ($path !== '.' && $this->is_dir($path)) {
215
-			$path .= '/';
216
-		}
217
-
218
-		return $this->doesObjectExist($path);
219
-	}
220
-
221
-	public function rmdir($path) {
222
-		$path = $this->normalizePath($path);
223
-
224
-		if (!$this->is_dir($path) || !$this->isDeletable($path)) {
225
-			return false;
226
-		}
227
-
228
-		$dh = $this->opendir($path);
229
-		while ($file = readdir($dh)) {
230
-			if (\OC\Files\Filesystem::isIgnoredDir($file)) {
231
-				continue;
232
-			}
233
-
234
-			if ($this->is_dir($path . '/' . $file)) {
235
-				$this->rmdir($path . '/' . $file);
236
-			} else {
237
-				$this->unlink($path . '/' . $file);
238
-			}
239
-		}
240
-
241
-		try {
242
-			$this->getContainer()->dataObject()->setName($path . '/')->delete();
243
-			$this->objectCache->remove($path . '/');
244
-		} catch (Exceptions\DeleteError $e) {
245
-			\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
246
-			return false;
247
-		}
248
-
249
-		return true;
250
-	}
251
-
252
-	public function opendir($path) {
253
-		$path = $this->normalizePath($path);
254
-
255
-		if ($path === '.') {
256
-			$path = '';
257
-		} else {
258
-			$path .= '/';
259
-		}
260
-
261
-		$path = str_replace('%23', '#', $path); // the prefix is sent as a query param, so revert the encoding of #
262
-
263
-		try {
264
-			$files = array();
265
-			/** @var OpenCloud\Common\Collection $objects */
266
-			$objects = $this->getContainer()->objectList(array(
267
-				'prefix' => $path,
268
-				'delimiter' => '/'
269
-			));
270
-
271
-			/** @var OpenCloud\ObjectStore\Resource\DataObject $object */
272
-			foreach ($objects as $object) {
273
-				$file = basename($object->getName());
274
-				if ($file !== basename($path) && $file !== '.') {
275
-					$files[] = $file;
276
-				}
277
-			}
278
-
279
-			return IteratorDirectory::wrap($files);
280
-		} catch (\Exception $e) {
281
-			\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
282
-			return false;
283
-		}
284
-
285
-	}
286
-
287
-	public function stat($path) {
288
-		$path = $this->normalizePath($path);
289
-
290
-		if ($path === '.') {
291
-			$path = '';
292
-		} else if ($this->is_dir($path)) {
293
-			$path .= '/';
294
-		}
295
-
296
-		try {
297
-			/** @var DataObject $object */
298
-			$object = $this->fetchObject($path);
299
-			if (!$object) {
300
-				return false;
301
-			}
302
-		} catch (ClientErrorResponseException $e) {
303
-			\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
304
-			return false;
305
-		}
306
-
307
-		$dateTime = \DateTime::createFromFormat(\DateTime::RFC1123, $object->getLastModified());
308
-		if ($dateTime !== false) {
309
-			$mtime = $dateTime->getTimestamp();
310
-		} else {
311
-			$mtime = null;
312
-		}
313
-		$objectMetadata = $object->getMetadata();
314
-		$metaTimestamp = $objectMetadata->getProperty('timestamp');
315
-		if (isset($metaTimestamp)) {
316
-			$mtime = $metaTimestamp;
317
-		}
318
-
319
-		if (!empty($mtime)) {
320
-			$mtime = floor($mtime);
321
-		}
322
-
323
-		$stat = array();
324
-		$stat['size'] = (int)$object->getContentLength();
325
-		$stat['mtime'] = $mtime;
326
-		$stat['atime'] = time();
327
-		return $stat;
328
-	}
329
-
330
-	public function filetype($path) {
331
-		$path = $this->normalizePath($path);
332
-
333
-		if ($path !== '.' && $this->doesObjectExist($path)) {
334
-			return 'file';
335
-		}
336
-
337
-		if ($path !== '.') {
338
-			$path .= '/';
339
-		}
340
-
341
-		if ($this->doesObjectExist($path)) {
342
-			return 'dir';
343
-		}
344
-	}
345
-
346
-	public function unlink($path) {
347
-		$path = $this->normalizePath($path);
348
-
349
-		if ($this->is_dir($path)) {
350
-			return $this->rmdir($path);
351
-		}
352
-
353
-		try {
354
-			$this->getContainer()->dataObject()->setName($path)->delete();
355
-			$this->objectCache->remove($path);
356
-			$this->objectCache->remove($path . '/');
357
-		} catch (ClientErrorResponseException $e) {
358
-			if ($e->getResponse()->getStatusCode() !== 404) {
359
-				\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
360
-			}
361
-			return false;
362
-		}
363
-
364
-		return true;
365
-	}
366
-
367
-	public function fopen($path, $mode) {
368
-		$path = $this->normalizePath($path);
369
-
370
-		switch ($mode) {
371
-			case 'a':
372
-			case 'ab':
373
-			case 'a+':
374
-				return false;
375
-			case 'r':
376
-			case 'rb':
377
-				try {
378
-					$c = $this->getContainer();
379
-					$streamFactory = new \Guzzle\Stream\PhpStreamRequestFactory();
380
-					/** @var \OpenCloud\Common\Http\Client $client */
381
-					$client = $c->getClient();
382
-					$streamInterface = $streamFactory->fromRequest($client->get($c->getUrl($path)));
383
-					$streamInterface->rewind();
384
-					$stream = $streamInterface->getStream();
385
-					stream_context_set_option($stream, 'swift','content', $streamInterface);
386
-					if(!strrpos($streamInterface
387
-						->getMetaData('wrapper_data')[0], '404 Not Found')) {
388
-						return $stream;
389
-					}
390
-					return false;
391
-				} catch (\Guzzle\Http\Exception\BadResponseException $e) {
392
-					\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
393
-					return false;
394
-				}
395
-			case 'w':
396
-			case 'wb':
397
-			case 'r+':
398
-			case 'w+':
399
-			case 'wb+':
400
-			case 'x':
401
-			case 'x+':
402
-			case 'c':
403
-			case 'c+':
404
-				if (strrpos($path, '.') !== false) {
405
-					$ext = substr($path, strrpos($path, '.'));
406
-				} else {
407
-					$ext = '';
408
-				}
409
-				$tmpFile = \OCP\Files::tmpFile($ext);
410
-				// Fetch existing file if required
411
-				if ($mode[0] !== 'w' && $this->file_exists($path)) {
412
-					if ($mode[0] === 'x') {
413
-						// File cannot already exist
414
-						return false;
415
-					}
416
-					$source = $this->fopen($path, 'r');
417
-					file_put_contents($tmpFile, $source);
418
-				}
419
-				$handle = fopen($tmpFile, $mode);
420
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
421
-					$this->writeBack($tmpFile, $path);
422
-				});
423
-		}
424
-	}
425
-
426
-	public function touch($path, $mtime = null) {
427
-		$path = $this->normalizePath($path);
428
-		if (is_null($mtime)) {
429
-			$mtime = time();
430
-		}
431
-		$metadata = array('timestamp' => $mtime);
432
-		if ($this->file_exists($path)) {
433
-			if ($this->is_dir($path) && $path !== '.') {
434
-				$path .= '/';
435
-			}
436
-
437
-			$object = $this->fetchObject($path);
438
-			if ($object->saveMetadata($metadata)) {
439
-				// invalidate target object to force repopulation on fetch
440
-				$this->objectCache->remove($path);
441
-			}
442
-			return true;
443
-		} else {
444
-			$mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
445
-			$customHeaders = array('content-type' => $mimeType);
446
-			$metadataHeaders = DataObject::stockHeaders($metadata);
447
-			$allHeaders = $customHeaders + $metadataHeaders;
448
-			$this->getContainer()->uploadObject($path, '', $allHeaders);
449
-			// invalidate target object to force repopulation on fetch
450
-			$this->objectCache->remove($path);
451
-			return true;
452
-		}
453
-	}
454
-
455
-	public function copy($path1, $path2) {
456
-		$path1 = $this->normalizePath($path1);
457
-		$path2 = $this->normalizePath($path2);
458
-
459
-		$fileType = $this->filetype($path1);
460
-		if ($fileType === 'file') {
461
-
462
-			// make way
463
-			$this->unlink($path2);
464
-
465
-			try {
466
-				$source = $this->fetchObject($path1);
467
-				$source->copy($this->bucket . '/' . $path2);
468
-				// invalidate target object to force repopulation on fetch
469
-				$this->objectCache->remove($path2);
470
-				$this->objectCache->remove($path2 . '/');
471
-			} catch (ClientErrorResponseException $e) {
472
-				\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
473
-				return false;
474
-			}
475
-
476
-		} else if ($fileType === 'dir') {
477
-
478
-			// make way
479
-			$this->unlink($path2);
480
-
481
-			try {
482
-				$source = $this->fetchObject($path1 . '/');
483
-				$source->copy($this->bucket . '/' . $path2 . '/');
484
-				// invalidate target object to force repopulation on fetch
485
-				$this->objectCache->remove($path2);
486
-				$this->objectCache->remove($path2 . '/');
487
-			} catch (ClientErrorResponseException $e) {
488
-				\OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
489
-				return false;
490
-			}
491
-
492
-			$dh = $this->opendir($path1);
493
-			while ($file = readdir($dh)) {
494
-				if (\OC\Files\Filesystem::isIgnoredDir($file)) {
495
-					continue;
496
-				}
497
-
498
-				$source = $path1 . '/' . $file;
499
-				$target = $path2 . '/' . $file;
500
-				$this->copy($source, $target);
501
-			}
502
-
503
-		} else {
504
-			//file does not exist
505
-			return false;
506
-		}
507
-
508
-		return true;
509
-	}
510
-
511
-	public function rename($path1, $path2) {
512
-		$path1 = $this->normalizePath($path1);
513
-		$path2 = $this->normalizePath($path2);
514
-
515
-		$fileType = $this->filetype($path1);
516
-
517
-		if ($fileType === 'dir' || $fileType === 'file') {
518
-			// copy
519
-			if ($this->copy($path1, $path2) === false) {
520
-				return false;
521
-			}
522
-
523
-			// cleanup
524
-			if ($this->unlink($path1) === false) {
525
-				$this->unlink($path2);
526
-				return false;
527
-			}
528
-
529
-			return true;
530
-		}
531
-
532
-		return false;
533
-	}
534
-
535
-	public function getId() {
536
-		return $this->id;
537
-	}
538
-
539
-	/**
540
-	 * Returns the connection
541
-	 *
542
-	 * @return OpenCloud\ObjectStore\Service connected client
543
-	 * @throws \Exception if connection could not be made
544
-	 */
545
-	public function getConnection() {
546
-		if (!is_null($this->connection)) {
547
-			return $this->connection;
548
-		}
549
-
550
-		$settings = array(
551
-			'username' => $this->params['user'],
552
-		);
553
-
554
-		if (!empty($this->params['password'])) {
555
-			$settings['password'] = $this->params['password'];
556
-		} else if (!empty($this->params['key'])) {
557
-			$settings['apiKey'] = $this->params['key'];
558
-		}
559
-
560
-		if (!empty($this->params['tenant'])) {
561
-			$settings['tenantName'] = $this->params['tenant'];
562
-		}
563
-
564
-		if (!empty($this->params['timeout'])) {
565
-			$settings['timeout'] = $this->params['timeout'];
566
-		}
567
-
568
-		if (isset($settings['apiKey'])) {
569
-			$this->anchor = new Rackspace($this->params['url'], $settings);
570
-		} else {
571
-			$this->anchor = new OpenStack($this->params['url'], $settings);
572
-		}
573
-
574
-		$connection = $this->anchor->objectStoreService($this->params['service_name'], $this->params['region']);
575
-
576
-		if (!empty($this->params['endpoint_url'])) {
577
-			$endpoint = $connection->getEndpoint();
578
-			$endpoint->setPublicUrl($this->params['endpoint_url']);
579
-			$endpoint->setPrivateUrl($this->params['endpoint_url']);
580
-			$connection->setEndpoint($endpoint);
581
-		}
582
-
583
-		$this->connection = $connection;
584
-
585
-		return $this->connection;
586
-	}
587
-
588
-	/**
589
-	 * Returns the initialized object store container.
590
-	 *
591
-	 * @return OpenCloud\ObjectStore\Resource\Container
592
-	 */
593
-	public function getContainer() {
594
-		if (!is_null($this->container)) {
595
-			return $this->container;
596
-		}
597
-
598
-		try {
599
-			$this->container = $this->getConnection()->getContainer($this->bucket);
600
-		} catch (ClientErrorResponseException $e) {
601
-			$this->container = $this->getConnection()->createContainer($this->bucket);
602
-		}
603
-
604
-		if (!$this->file_exists('.')) {
605
-			$this->mkdir('.');
606
-		}
607
-
608
-		return $this->container;
609
-	}
610
-
611
-	public function writeBack($tmpFile, $path) {
612
-		$fileData = fopen($tmpFile, 'r');
613
-		$this->getContainer()->uploadObject($path, $fileData);
614
-		// invalidate target object to force repopulation on fetch
615
-		$this->objectCache->remove($path);
616
-		unlink($tmpFile);
617
-	}
618
-
619
-	public function hasUpdated($path, $time) {
620
-		if ($this->is_file($path)) {
621
-			return parent::hasUpdated($path, $time);
622
-		}
623
-		$path = $this->normalizePath($path);
624
-		$dh = $this->opendir($path);
625
-		$content = array();
626
-		while (($file = readdir($dh)) !== false) {
627
-			$content[] = $file;
628
-		}
629
-		if ($path === '.') {
630
-			$path = '';
631
-		}
632
-		$cachedContent = $this->getCache()->getFolderContents($path);
633
-		$cachedNames = array_map(function ($content) {
634
-			return $content['name'];
635
-		}, $cachedContent);
636
-		sort($cachedNames);
637
-		sort($content);
638
-		return $cachedNames !== $content;
639
-	}
640
-
641
-	/**
642
-	 * check if curl is installed
643
-	 */
644
-	public static function checkDependencies() {
645
-		return true;
646
-	}
51
+    /**
52
+     * @var \OpenCloud\ObjectStore\Service
53
+     */
54
+    private $connection;
55
+    /**
56
+     * @var \OpenCloud\ObjectStore\Resource\Container
57
+     */
58
+    private $container;
59
+    /**
60
+     * @var \OpenCloud\OpenStack
61
+     */
62
+    private $anchor;
63
+    /**
64
+     * @var string
65
+     */
66
+    private $bucket;
67
+    /**
68
+     * Connection parameters
69
+     *
70
+     * @var array
71
+     */
72
+    private $params;
73
+
74
+    /** @var string  */
75
+    private $id;
76
+
77
+    /**
78
+     * Key value cache mapping path to data object. Maps path to
79
+     * \OpenCloud\OpenStack\ObjectStorage\Resource\DataObject for existing
80
+     * paths and path to false for not existing paths.
81
+     * @var \OCP\ICache
82
+     */
83
+    private $objectCache;
84
+
85
+    /**
86
+     * @param string $path
87
+     */
88
+    private function normalizePath($path) {
89
+        $path = trim($path, '/');
90
+
91
+        if (!$path) {
92
+            $path = '.';
93
+        }
94
+
95
+        $path = str_replace('#', '%23', $path);
96
+
97
+        return $path;
98
+    }
99
+
100
+    const SUBCONTAINER_FILE = '.subcontainers';
101
+
102
+    /**
103
+     * translate directory path to container name
104
+     *
105
+     * @param string $path
106
+     * @return string
107
+     */
108
+
109
+    /**
110
+     * Fetches an object from the API.
111
+     * If the object is cached already or a
112
+     * failed "doesn't exist" response was cached,
113
+     * that one will be returned.
114
+     *
115
+     * @param string $path
116
+     * @return \OpenCloud\ObjectStore\Resource\DataObject|bool object
117
+     * or false if the object did not exist
118
+     */
119
+    private function fetchObject($path) {
120
+        if ($this->objectCache->hasKey($path)) {
121
+            // might be "false" if object did not exist from last check
122
+            return $this->objectCache->get($path);
123
+        }
124
+        try {
125
+            $object = $this->getContainer()->getPartialObject($path);
126
+            $this->objectCache->set($path, $object);
127
+            return $object;
128
+        } catch (ClientErrorResponseException $e) {
129
+            // this exception happens when the object does not exist, which
130
+            // is expected in most cases
131
+            $this->objectCache->set($path, false);
132
+            return false;
133
+        } catch (ClientErrorResponseException $e) {
134
+            // Expected response is "404 Not Found", so only log if it isn't
135
+            if ($e->getResponse()->getStatusCode() !== 404) {
136
+                \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
137
+            }
138
+            return false;
139
+        }
140
+    }
141
+
142
+    /**
143
+     * Returns whether the given path exists.
144
+     *
145
+     * @param string $path
146
+     *
147
+     * @return bool true if the object exist, false otherwise
148
+     */
149
+    private function doesObjectExist($path) {
150
+        return $this->fetchObject($path) !== false;
151
+    }
152
+
153
+    public function __construct($params) {
154
+        if ((empty($params['key']) and empty($params['password']))
155
+            or empty($params['user']) or empty($params['bucket'])
156
+            or empty($params['region'])
157
+        ) {
158
+            throw new \Exception("API Key or password, Username, Bucket and Region have to be configured.");
159
+        }
160
+
161
+        $this->id = 'swift::' . $params['user'] . md5($params['bucket']);
162
+
163
+        $bucketUrl = Url::factory($params['bucket']);
164
+        if ($bucketUrl->isAbsolute()) {
165
+            $this->bucket = end(($bucketUrl->getPathSegments()));
166
+            $params['endpoint_url'] = $bucketUrl->addPath('..')->normalizePath();
167
+        } else {
168
+            $this->bucket = $params['bucket'];
169
+        }
170
+
171
+        if (empty($params['url'])) {
172
+            $params['url'] = 'https://identity.api.rackspacecloud.com/v2.0/';
173
+        }
174
+
175
+        if (empty($params['service_name'])) {
176
+            $params['service_name'] = 'cloudFiles';
177
+        }
178
+
179
+        $this->params = $params;
180
+        // FIXME: private class...
181
+        $this->objectCache = new \OC\Cache\CappedMemoryCache();
182
+    }
183
+
184
+    public function mkdir($path) {
185
+        $path = $this->normalizePath($path);
186
+
187
+        if ($this->is_dir($path)) {
188
+            return false;
189
+        }
190
+
191
+        if ($path !== '.') {
192
+            $path .= '/';
193
+        }
194
+
195
+        try {
196
+            $customHeaders = array('content-type' => 'httpd/unix-directory');
197
+            $metadataHeaders = DataObject::stockHeaders(array());
198
+            $allHeaders = $customHeaders + $metadataHeaders;
199
+            $this->getContainer()->uploadObject($path, '', $allHeaders);
200
+            // invalidate so that the next access gets the real object
201
+            // with all properties
202
+            $this->objectCache->remove($path);
203
+        } catch (Exceptions\CreateUpdateError $e) {
204
+            \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
205
+            return false;
206
+        }
207
+
208
+        return true;
209
+    }
210
+
211
+    public function file_exists($path) {
212
+        $path = $this->normalizePath($path);
213
+
214
+        if ($path !== '.' && $this->is_dir($path)) {
215
+            $path .= '/';
216
+        }
217
+
218
+        return $this->doesObjectExist($path);
219
+    }
220
+
221
+    public function rmdir($path) {
222
+        $path = $this->normalizePath($path);
223
+
224
+        if (!$this->is_dir($path) || !$this->isDeletable($path)) {
225
+            return false;
226
+        }
227
+
228
+        $dh = $this->opendir($path);
229
+        while ($file = readdir($dh)) {
230
+            if (\OC\Files\Filesystem::isIgnoredDir($file)) {
231
+                continue;
232
+            }
233
+
234
+            if ($this->is_dir($path . '/' . $file)) {
235
+                $this->rmdir($path . '/' . $file);
236
+            } else {
237
+                $this->unlink($path . '/' . $file);
238
+            }
239
+        }
240
+
241
+        try {
242
+            $this->getContainer()->dataObject()->setName($path . '/')->delete();
243
+            $this->objectCache->remove($path . '/');
244
+        } catch (Exceptions\DeleteError $e) {
245
+            \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
246
+            return false;
247
+        }
248
+
249
+        return true;
250
+    }
251
+
252
+    public function opendir($path) {
253
+        $path = $this->normalizePath($path);
254
+
255
+        if ($path === '.') {
256
+            $path = '';
257
+        } else {
258
+            $path .= '/';
259
+        }
260
+
261
+        $path = str_replace('%23', '#', $path); // the prefix is sent as a query param, so revert the encoding of #
262
+
263
+        try {
264
+            $files = array();
265
+            /** @var OpenCloud\Common\Collection $objects */
266
+            $objects = $this->getContainer()->objectList(array(
267
+                'prefix' => $path,
268
+                'delimiter' => '/'
269
+            ));
270
+
271
+            /** @var OpenCloud\ObjectStore\Resource\DataObject $object */
272
+            foreach ($objects as $object) {
273
+                $file = basename($object->getName());
274
+                if ($file !== basename($path) && $file !== '.') {
275
+                    $files[] = $file;
276
+                }
277
+            }
278
+
279
+            return IteratorDirectory::wrap($files);
280
+        } catch (\Exception $e) {
281
+            \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
282
+            return false;
283
+        }
284
+
285
+    }
286
+
287
+    public function stat($path) {
288
+        $path = $this->normalizePath($path);
289
+
290
+        if ($path === '.') {
291
+            $path = '';
292
+        } else if ($this->is_dir($path)) {
293
+            $path .= '/';
294
+        }
295
+
296
+        try {
297
+            /** @var DataObject $object */
298
+            $object = $this->fetchObject($path);
299
+            if (!$object) {
300
+                return false;
301
+            }
302
+        } catch (ClientErrorResponseException $e) {
303
+            \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
304
+            return false;
305
+        }
306
+
307
+        $dateTime = \DateTime::createFromFormat(\DateTime::RFC1123, $object->getLastModified());
308
+        if ($dateTime !== false) {
309
+            $mtime = $dateTime->getTimestamp();
310
+        } else {
311
+            $mtime = null;
312
+        }
313
+        $objectMetadata = $object->getMetadata();
314
+        $metaTimestamp = $objectMetadata->getProperty('timestamp');
315
+        if (isset($metaTimestamp)) {
316
+            $mtime = $metaTimestamp;
317
+        }
318
+
319
+        if (!empty($mtime)) {
320
+            $mtime = floor($mtime);
321
+        }
322
+
323
+        $stat = array();
324
+        $stat['size'] = (int)$object->getContentLength();
325
+        $stat['mtime'] = $mtime;
326
+        $stat['atime'] = time();
327
+        return $stat;
328
+    }
329
+
330
+    public function filetype($path) {
331
+        $path = $this->normalizePath($path);
332
+
333
+        if ($path !== '.' && $this->doesObjectExist($path)) {
334
+            return 'file';
335
+        }
336
+
337
+        if ($path !== '.') {
338
+            $path .= '/';
339
+        }
340
+
341
+        if ($this->doesObjectExist($path)) {
342
+            return 'dir';
343
+        }
344
+    }
345
+
346
+    public function unlink($path) {
347
+        $path = $this->normalizePath($path);
348
+
349
+        if ($this->is_dir($path)) {
350
+            return $this->rmdir($path);
351
+        }
352
+
353
+        try {
354
+            $this->getContainer()->dataObject()->setName($path)->delete();
355
+            $this->objectCache->remove($path);
356
+            $this->objectCache->remove($path . '/');
357
+        } catch (ClientErrorResponseException $e) {
358
+            if ($e->getResponse()->getStatusCode() !== 404) {
359
+                \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
360
+            }
361
+            return false;
362
+        }
363
+
364
+        return true;
365
+    }
366
+
367
+    public function fopen($path, $mode) {
368
+        $path = $this->normalizePath($path);
369
+
370
+        switch ($mode) {
371
+            case 'a':
372
+            case 'ab':
373
+            case 'a+':
374
+                return false;
375
+            case 'r':
376
+            case 'rb':
377
+                try {
378
+                    $c = $this->getContainer();
379
+                    $streamFactory = new \Guzzle\Stream\PhpStreamRequestFactory();
380
+                    /** @var \OpenCloud\Common\Http\Client $client */
381
+                    $client = $c->getClient();
382
+                    $streamInterface = $streamFactory->fromRequest($client->get($c->getUrl($path)));
383
+                    $streamInterface->rewind();
384
+                    $stream = $streamInterface->getStream();
385
+                    stream_context_set_option($stream, 'swift','content', $streamInterface);
386
+                    if(!strrpos($streamInterface
387
+                        ->getMetaData('wrapper_data')[0], '404 Not Found')) {
388
+                        return $stream;
389
+                    }
390
+                    return false;
391
+                } catch (\Guzzle\Http\Exception\BadResponseException $e) {
392
+                    \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
393
+                    return false;
394
+                }
395
+            case 'w':
396
+            case 'wb':
397
+            case 'r+':
398
+            case 'w+':
399
+            case 'wb+':
400
+            case 'x':
401
+            case 'x+':
402
+            case 'c':
403
+            case 'c+':
404
+                if (strrpos($path, '.') !== false) {
405
+                    $ext = substr($path, strrpos($path, '.'));
406
+                } else {
407
+                    $ext = '';
408
+                }
409
+                $tmpFile = \OCP\Files::tmpFile($ext);
410
+                // Fetch existing file if required
411
+                if ($mode[0] !== 'w' && $this->file_exists($path)) {
412
+                    if ($mode[0] === 'x') {
413
+                        // File cannot already exist
414
+                        return false;
415
+                    }
416
+                    $source = $this->fopen($path, 'r');
417
+                    file_put_contents($tmpFile, $source);
418
+                }
419
+                $handle = fopen($tmpFile, $mode);
420
+                return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
421
+                    $this->writeBack($tmpFile, $path);
422
+                });
423
+        }
424
+    }
425
+
426
+    public function touch($path, $mtime = null) {
427
+        $path = $this->normalizePath($path);
428
+        if (is_null($mtime)) {
429
+            $mtime = time();
430
+        }
431
+        $metadata = array('timestamp' => $mtime);
432
+        if ($this->file_exists($path)) {
433
+            if ($this->is_dir($path) && $path !== '.') {
434
+                $path .= '/';
435
+            }
436
+
437
+            $object = $this->fetchObject($path);
438
+            if ($object->saveMetadata($metadata)) {
439
+                // invalidate target object to force repopulation on fetch
440
+                $this->objectCache->remove($path);
441
+            }
442
+            return true;
443
+        } else {
444
+            $mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
445
+            $customHeaders = array('content-type' => $mimeType);
446
+            $metadataHeaders = DataObject::stockHeaders($metadata);
447
+            $allHeaders = $customHeaders + $metadataHeaders;
448
+            $this->getContainer()->uploadObject($path, '', $allHeaders);
449
+            // invalidate target object to force repopulation on fetch
450
+            $this->objectCache->remove($path);
451
+            return true;
452
+        }
453
+    }
454
+
455
+    public function copy($path1, $path2) {
456
+        $path1 = $this->normalizePath($path1);
457
+        $path2 = $this->normalizePath($path2);
458
+
459
+        $fileType = $this->filetype($path1);
460
+        if ($fileType === 'file') {
461
+
462
+            // make way
463
+            $this->unlink($path2);
464
+
465
+            try {
466
+                $source = $this->fetchObject($path1);
467
+                $source->copy($this->bucket . '/' . $path2);
468
+                // invalidate target object to force repopulation on fetch
469
+                $this->objectCache->remove($path2);
470
+                $this->objectCache->remove($path2 . '/');
471
+            } catch (ClientErrorResponseException $e) {
472
+                \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
473
+                return false;
474
+            }
475
+
476
+        } else if ($fileType === 'dir') {
477
+
478
+            // make way
479
+            $this->unlink($path2);
480
+
481
+            try {
482
+                $source = $this->fetchObject($path1 . '/');
483
+                $source->copy($this->bucket . '/' . $path2 . '/');
484
+                // invalidate target object to force repopulation on fetch
485
+                $this->objectCache->remove($path2);
486
+                $this->objectCache->remove($path2 . '/');
487
+            } catch (ClientErrorResponseException $e) {
488
+                \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR);
489
+                return false;
490
+            }
491
+
492
+            $dh = $this->opendir($path1);
493
+            while ($file = readdir($dh)) {
494
+                if (\OC\Files\Filesystem::isIgnoredDir($file)) {
495
+                    continue;
496
+                }
497
+
498
+                $source = $path1 . '/' . $file;
499
+                $target = $path2 . '/' . $file;
500
+                $this->copy($source, $target);
501
+            }
502
+
503
+        } else {
504
+            //file does not exist
505
+            return false;
506
+        }
507
+
508
+        return true;
509
+    }
510
+
511
+    public function rename($path1, $path2) {
512
+        $path1 = $this->normalizePath($path1);
513
+        $path2 = $this->normalizePath($path2);
514
+
515
+        $fileType = $this->filetype($path1);
516
+
517
+        if ($fileType === 'dir' || $fileType === 'file') {
518
+            // copy
519
+            if ($this->copy($path1, $path2) === false) {
520
+                return false;
521
+            }
522
+
523
+            // cleanup
524
+            if ($this->unlink($path1) === false) {
525
+                $this->unlink($path2);
526
+                return false;
527
+            }
528
+
529
+            return true;
530
+        }
531
+
532
+        return false;
533
+    }
534
+
535
+    public function getId() {
536
+        return $this->id;
537
+    }
538
+
539
+    /**
540
+     * Returns the connection
541
+     *
542
+     * @return OpenCloud\ObjectStore\Service connected client
543
+     * @throws \Exception if connection could not be made
544
+     */
545
+    public function getConnection() {
546
+        if (!is_null($this->connection)) {
547
+            return $this->connection;
548
+        }
549
+
550
+        $settings = array(
551
+            'username' => $this->params['user'],
552
+        );
553
+
554
+        if (!empty($this->params['password'])) {
555
+            $settings['password'] = $this->params['password'];
556
+        } else if (!empty($this->params['key'])) {
557
+            $settings['apiKey'] = $this->params['key'];
558
+        }
559
+
560
+        if (!empty($this->params['tenant'])) {
561
+            $settings['tenantName'] = $this->params['tenant'];
562
+        }
563
+
564
+        if (!empty($this->params['timeout'])) {
565
+            $settings['timeout'] = $this->params['timeout'];
566
+        }
567
+
568
+        if (isset($settings['apiKey'])) {
569
+            $this->anchor = new Rackspace($this->params['url'], $settings);
570
+        } else {
571
+            $this->anchor = new OpenStack($this->params['url'], $settings);
572
+        }
573
+
574
+        $connection = $this->anchor->objectStoreService($this->params['service_name'], $this->params['region']);
575
+
576
+        if (!empty($this->params['endpoint_url'])) {
577
+            $endpoint = $connection->getEndpoint();
578
+            $endpoint->setPublicUrl($this->params['endpoint_url']);
579
+            $endpoint->setPrivateUrl($this->params['endpoint_url']);
580
+            $connection->setEndpoint($endpoint);
581
+        }
582
+
583
+        $this->connection = $connection;
584
+
585
+        return $this->connection;
586
+    }
587
+
588
+    /**
589
+     * Returns the initialized object store container.
590
+     *
591
+     * @return OpenCloud\ObjectStore\Resource\Container
592
+     */
593
+    public function getContainer() {
594
+        if (!is_null($this->container)) {
595
+            return $this->container;
596
+        }
597
+
598
+        try {
599
+            $this->container = $this->getConnection()->getContainer($this->bucket);
600
+        } catch (ClientErrorResponseException $e) {
601
+            $this->container = $this->getConnection()->createContainer($this->bucket);
602
+        }
603
+
604
+        if (!$this->file_exists('.')) {
605
+            $this->mkdir('.');
606
+        }
607
+
608
+        return $this->container;
609
+    }
610
+
611
+    public function writeBack($tmpFile, $path) {
612
+        $fileData = fopen($tmpFile, 'r');
613
+        $this->getContainer()->uploadObject($path, $fileData);
614
+        // invalidate target object to force repopulation on fetch
615
+        $this->objectCache->remove($path);
616
+        unlink($tmpFile);
617
+    }
618
+
619
+    public function hasUpdated($path, $time) {
620
+        if ($this->is_file($path)) {
621
+            return parent::hasUpdated($path, $time);
622
+        }
623
+        $path = $this->normalizePath($path);
624
+        $dh = $this->opendir($path);
625
+        $content = array();
626
+        while (($file = readdir($dh)) !== false) {
627
+            $content[] = $file;
628
+        }
629
+        if ($path === '.') {
630
+            $path = '';
631
+        }
632
+        $cachedContent = $this->getCache()->getFolderContents($path);
633
+        $cachedNames = array_map(function ($content) {
634
+            return $content['name'];
635
+        }, $cachedContent);
636
+        sort($cachedNames);
637
+        sort($content);
638
+        return $cachedNames !== $content;
639
+    }
640
+
641
+    /**
642
+     * check if curl is installed
643
+     */
644
+    public static function checkDependencies() {
645
+        return true;
646
+    }
647 647
 
648 648
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/Controller/ShareController.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -597,7 +597,7 @@
 block discarded – undo
597 597
 	 * publish activity
598 598
 	 *
599 599
 	 * @param string $subject
600
-	 * @param array $parameters
600
+	 * @param string[] $parameters
601 601
 	 * @param string $affectedUser
602 602
 	 * @param int $fileId
603 603
 	 * @param string $filePath
Please login to merge, or discard this patch.
Indentation   +555 added lines, -555 removed lines patch added patch discarded remove patch
@@ -64,563 +64,563 @@
 block discarded – undo
64 64
  */
65 65
 class ShareController extends Controller {
66 66
 
67
-	/** @var IConfig */
68
-	protected $config;
69
-	/** @var IURLGenerator */
70
-	protected $urlGenerator;
71
-	/** @var IUserManager */
72
-	protected $userManager;
73
-	/** @var ILogger */
74
-	protected $logger;
75
-	/** @var \OCP\Activity\IManager */
76
-	protected $activityManager;
77
-	/** @var \OCP\Share\IManager */
78
-	protected $shareManager;
79
-	/** @var ISession */
80
-	protected $session;
81
-	/** @var IPreview */
82
-	protected $previewManager;
83
-	/** @var IRootFolder */
84
-	protected $rootFolder;
85
-	/** @var FederatedShareProvider */
86
-	protected $federatedShareProvider;
87
-	/** @var EventDispatcherInterface */
88
-	protected $eventDispatcher;
89
-	/** @var IL10N */
90
-	protected $l10n;
91
-	/** @var Defaults */
92
-	protected $defaults;
93
-
94
-	/**
95
-	 * @param string $appName
96
-	 * @param IRequest $request
97
-	 * @param IConfig $config
98
-	 * @param IURLGenerator $urlGenerator
99
-	 * @param IUserManager $userManager
100
-	 * @param ILogger $logger
101
-	 * @param \OCP\Activity\IManager $activityManager
102
-	 * @param \OCP\Share\IManager $shareManager
103
-	 * @param ISession $session
104
-	 * @param IPreview $previewManager
105
-	 * @param IRootFolder $rootFolder
106
-	 * @param FederatedShareProvider $federatedShareProvider
107
-	 * @param EventDispatcherInterface $eventDispatcher
108
-	 * @param IL10N $l10n
109
-	 * @param Defaults $defaults
110
-	 */
111
-	public function __construct($appName,
112
-								IRequest $request,
113
-								IConfig $config,
114
-								IURLGenerator $urlGenerator,
115
-								IUserManager $userManager,
116
-								ILogger $logger,
117
-								\OCP\Activity\IManager $activityManager,
118
-								\OCP\Share\IManager $shareManager,
119
-								ISession $session,
120
-								IPreview $previewManager,
121
-								IRootFolder $rootFolder,
122
-								FederatedShareProvider $federatedShareProvider,
123
-								EventDispatcherInterface $eventDispatcher,
124
-								IL10N $l10n,
125
-								Defaults $defaults) {
126
-		parent::__construct($appName, $request);
127
-
128
-		$this->config = $config;
129
-		$this->urlGenerator = $urlGenerator;
130
-		$this->userManager = $userManager;
131
-		$this->logger = $logger;
132
-		$this->activityManager = $activityManager;
133
-		$this->shareManager = $shareManager;
134
-		$this->session = $session;
135
-		$this->previewManager = $previewManager;
136
-		$this->rootFolder = $rootFolder;
137
-		$this->federatedShareProvider = $federatedShareProvider;
138
-		$this->eventDispatcher = $eventDispatcher;
139
-		$this->l10n = $l10n;
140
-		$this->defaults = $defaults;
141
-	}
142
-
143
-	/**
144
-	 * @PublicPage
145
-	 * @NoCSRFRequired
146
-	 *
147
-	 * @param string $token
148
-	 * @return TemplateResponse|RedirectResponse
149
-	 */
150
-	public function showAuthenticate($token) {
151
-		$share = $this->shareManager->getShareByToken($token);
152
-
153
-		if($this->linkShareAuth($share)) {
154
-			return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token)));
155
-		}
156
-
157
-		return new TemplateResponse($this->appName, 'authenticate', array(), 'guest');
158
-	}
159
-
160
-	/**
161
-	 * @PublicPage
162
-	 * @UseSession
163
-	 * @BruteForceProtection(action=publicLinkAuth)
164
-	 *
165
-	 * Authenticates against password-protected shares
166
-	 * @param string $token
167
-	 * @param string $password
168
-	 * @return RedirectResponse|TemplateResponse|NotFoundResponse
169
-	 */
170
-	public function authenticate($token, $password = '') {
171
-
172
-		// Check whether share exists
173
-		try {
174
-			$share = $this->shareManager->getShareByToken($token);
175
-		} catch (ShareNotFound $e) {
176
-			return new NotFoundResponse();
177
-		}
178
-
179
-		$authenticate = $this->linkShareAuth($share, $password);
180
-
181
-		if($authenticate === true) {
182
-			return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token)));
183
-		}
184
-
185
-		$response = new TemplateResponse($this->appName, 'authenticate', array('wrongpw' => true), 'guest');
186
-		$response->throttle();
187
-		return $response;
188
-	}
189
-
190
-	/**
191
-	 * Authenticate a link item with the given password.
192
-	 * Or use the session if no password is provided.
193
-	 *
194
-	 * This is a modified version of Helper::authenticate
195
-	 * TODO: Try to merge back eventually with Helper::authenticate
196
-	 *
197
-	 * @param \OCP\Share\IShare $share
198
-	 * @param string|null $password
199
-	 * @return bool
200
-	 */
201
-	private function linkShareAuth(\OCP\Share\IShare $share, $password = null) {
202
-		if ($password !== null) {
203
-			if ($this->shareManager->checkPassword($share, $password)) {
204
-				$this->session->set('public_link_authenticated', (string)$share->getId());
205
-			} else {
206
-				$this->emitAccessShareHook($share, 403, 'Wrong password');
207
-				return false;
208
-			}
209
-		} else {
210
-			// not authenticated ?
211
-			if ( ! $this->session->exists('public_link_authenticated')
212
-				|| $this->session->get('public_link_authenticated') !== (string)$share->getId()) {
213
-				return false;
214
-			}
215
-		}
216
-		return true;
217
-	}
218
-
219
-	/**
220
-	 * throws hooks when a share is attempted to be accessed
221
-	 *
222
-	 * @param \OCP\Share\IShare|string $share the Share instance if available,
223
-	 * otherwise token
224
-	 * @param int $errorCode
225
-	 * @param string $errorMessage
226
-	 * @throws \OC\HintException
227
-	 * @throws \OC\ServerNotAvailableException
228
-	 */
229
-	protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
230
-		$itemType = $itemSource = $uidOwner = '';
231
-		$token = $share;
232
-		$exception = null;
233
-		if($share instanceof \OCP\Share\IShare) {
234
-			try {
235
-				$token = $share->getToken();
236
-				$uidOwner = $share->getSharedBy();
237
-				$itemType = $share->getNodeType();
238
-				$itemSource = $share->getNodeId();
239
-			} catch (\Exception $e) {
240
-				// we log what we know and pass on the exception afterwards
241
-				$exception = $e;
242
-			}
243
-		}
244
-		\OC_Hook::emit('OCP\Share', 'share_link_access', [
245
-			'itemType' => $itemType,
246
-			'itemSource' => $itemSource,
247
-			'uidOwner' => $uidOwner,
248
-			'token' => $token,
249
-			'errorCode' => $errorCode,
250
-			'errorMessage' => $errorMessage,
251
-		]);
252
-		if(!is_null($exception)) {
253
-			throw $exception;
254
-		}
255
-	}
256
-
257
-	/**
258
-	 * Validate the permissions of the share
259
-	 *
260
-	 * @param Share\IShare $share
261
-	 * @return bool
262
-	 */
263
-	private function validateShare(\OCP\Share\IShare $share) {
264
-		return $share->getNode()->isReadable() && $share->getNode()->isShareable();
265
-	}
266
-
267
-	/**
268
-	 * @PublicPage
269
-	 * @NoCSRFRequired
270
-	 *
271
-	 * @param string $token
272
-	 * @param string $path
273
-	 * @return TemplateResponse|RedirectResponse|NotFoundResponse
274
-	 * @throws NotFoundException
275
-	 * @throws \Exception
276
-	 */
277
-	public function showShare($token, $path = '') {
278
-		\OC_User::setIncognitoMode(true);
279
-
280
-		// Check whether share exists
281
-		try {
282
-			$share = $this->shareManager->getShareByToken($token);
283
-		} catch (ShareNotFound $e) {
284
-			$this->emitAccessShareHook($token, 404, 'Share not found');
285
-			return new NotFoundResponse();
286
-		}
287
-
288
-		// Share is password protected - check whether the user is permitted to access the share
289
-		if ($share->getPassword() !== null && !$this->linkShareAuth($share)) {
290
-			return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate',
291
-				array('token' => $token)));
292
-		}
293
-
294
-		if (!$this->validateShare($share)) {
295
-			throw new NotFoundException();
296
-		}
297
-		// We can't get the path of a file share
298
-		try {
299
-			if ($share->getNode() instanceof \OCP\Files\File && $path !== '') {
300
-				$this->emitAccessShareHook($share, 404, 'Share not found');
301
-				throw new NotFoundException();
302
-			}
303
-		} catch (\Exception $e) {
304
-			$this->emitAccessShareHook($share, 404, 'Share not found');
305
-			throw $e;
306
-		}
307
-
308
-		$shareTmpl = [];
309
-		$shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
310
-		$shareTmpl['owner'] = $share->getShareOwner();
311
-		$shareTmpl['filename'] = $share->getNode()->getName();
312
-		$shareTmpl['directory_path'] = $share->getTarget();
313
-		$shareTmpl['mimetype'] = $share->getNode()->getMimetype();
314
-		$shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($share->getNode()->getMimetype());
315
-		$shareTmpl['dirToken'] = $token;
316
-		$shareTmpl['sharingToken'] = $token;
317
-		$shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
318
-		$shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
319
-		$shareTmpl['dir'] = '';
320
-		$shareTmpl['nonHumanFileSize'] = $share->getNode()->getSize();
321
-		$shareTmpl['fileSize'] = \OCP\Util::humanFileSize($share->getNode()->getSize());
322
-
323
-		// Show file list
324
-		$hideFileList = false;
325
-		if ($share->getNode() instanceof \OCP\Files\Folder) {
326
-			/** @var \OCP\Files\Folder $rootFolder */
327
-			$rootFolder = $share->getNode();
328
-
329
-			try {
330
-				$folderNode = $rootFolder->get($path);
331
-			} catch (\OCP\Files\NotFoundException $e) {
332
-				$this->emitAccessShareHook($share, 404, 'Share not found');
333
-				throw new NotFoundException();
334
-			}
335
-
336
-			$shareTmpl['dir'] = $rootFolder->getRelativePath($folderNode->getPath());
337
-
338
-			/*
67
+    /** @var IConfig */
68
+    protected $config;
69
+    /** @var IURLGenerator */
70
+    protected $urlGenerator;
71
+    /** @var IUserManager */
72
+    protected $userManager;
73
+    /** @var ILogger */
74
+    protected $logger;
75
+    /** @var \OCP\Activity\IManager */
76
+    protected $activityManager;
77
+    /** @var \OCP\Share\IManager */
78
+    protected $shareManager;
79
+    /** @var ISession */
80
+    protected $session;
81
+    /** @var IPreview */
82
+    protected $previewManager;
83
+    /** @var IRootFolder */
84
+    protected $rootFolder;
85
+    /** @var FederatedShareProvider */
86
+    protected $federatedShareProvider;
87
+    /** @var EventDispatcherInterface */
88
+    protected $eventDispatcher;
89
+    /** @var IL10N */
90
+    protected $l10n;
91
+    /** @var Defaults */
92
+    protected $defaults;
93
+
94
+    /**
95
+     * @param string $appName
96
+     * @param IRequest $request
97
+     * @param IConfig $config
98
+     * @param IURLGenerator $urlGenerator
99
+     * @param IUserManager $userManager
100
+     * @param ILogger $logger
101
+     * @param \OCP\Activity\IManager $activityManager
102
+     * @param \OCP\Share\IManager $shareManager
103
+     * @param ISession $session
104
+     * @param IPreview $previewManager
105
+     * @param IRootFolder $rootFolder
106
+     * @param FederatedShareProvider $federatedShareProvider
107
+     * @param EventDispatcherInterface $eventDispatcher
108
+     * @param IL10N $l10n
109
+     * @param Defaults $defaults
110
+     */
111
+    public function __construct($appName,
112
+                                IRequest $request,
113
+                                IConfig $config,
114
+                                IURLGenerator $urlGenerator,
115
+                                IUserManager $userManager,
116
+                                ILogger $logger,
117
+                                \OCP\Activity\IManager $activityManager,
118
+                                \OCP\Share\IManager $shareManager,
119
+                                ISession $session,
120
+                                IPreview $previewManager,
121
+                                IRootFolder $rootFolder,
122
+                                FederatedShareProvider $federatedShareProvider,
123
+                                EventDispatcherInterface $eventDispatcher,
124
+                                IL10N $l10n,
125
+                                Defaults $defaults) {
126
+        parent::__construct($appName, $request);
127
+
128
+        $this->config = $config;
129
+        $this->urlGenerator = $urlGenerator;
130
+        $this->userManager = $userManager;
131
+        $this->logger = $logger;
132
+        $this->activityManager = $activityManager;
133
+        $this->shareManager = $shareManager;
134
+        $this->session = $session;
135
+        $this->previewManager = $previewManager;
136
+        $this->rootFolder = $rootFolder;
137
+        $this->federatedShareProvider = $federatedShareProvider;
138
+        $this->eventDispatcher = $eventDispatcher;
139
+        $this->l10n = $l10n;
140
+        $this->defaults = $defaults;
141
+    }
142
+
143
+    /**
144
+     * @PublicPage
145
+     * @NoCSRFRequired
146
+     *
147
+     * @param string $token
148
+     * @return TemplateResponse|RedirectResponse
149
+     */
150
+    public function showAuthenticate($token) {
151
+        $share = $this->shareManager->getShareByToken($token);
152
+
153
+        if($this->linkShareAuth($share)) {
154
+            return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token)));
155
+        }
156
+
157
+        return new TemplateResponse($this->appName, 'authenticate', array(), 'guest');
158
+    }
159
+
160
+    /**
161
+     * @PublicPage
162
+     * @UseSession
163
+     * @BruteForceProtection(action=publicLinkAuth)
164
+     *
165
+     * Authenticates against password-protected shares
166
+     * @param string $token
167
+     * @param string $password
168
+     * @return RedirectResponse|TemplateResponse|NotFoundResponse
169
+     */
170
+    public function authenticate($token, $password = '') {
171
+
172
+        // Check whether share exists
173
+        try {
174
+            $share = $this->shareManager->getShareByToken($token);
175
+        } catch (ShareNotFound $e) {
176
+            return new NotFoundResponse();
177
+        }
178
+
179
+        $authenticate = $this->linkShareAuth($share, $password);
180
+
181
+        if($authenticate === true) {
182
+            return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token)));
183
+        }
184
+
185
+        $response = new TemplateResponse($this->appName, 'authenticate', array('wrongpw' => true), 'guest');
186
+        $response->throttle();
187
+        return $response;
188
+    }
189
+
190
+    /**
191
+     * Authenticate a link item with the given password.
192
+     * Or use the session if no password is provided.
193
+     *
194
+     * This is a modified version of Helper::authenticate
195
+     * TODO: Try to merge back eventually with Helper::authenticate
196
+     *
197
+     * @param \OCP\Share\IShare $share
198
+     * @param string|null $password
199
+     * @return bool
200
+     */
201
+    private function linkShareAuth(\OCP\Share\IShare $share, $password = null) {
202
+        if ($password !== null) {
203
+            if ($this->shareManager->checkPassword($share, $password)) {
204
+                $this->session->set('public_link_authenticated', (string)$share->getId());
205
+            } else {
206
+                $this->emitAccessShareHook($share, 403, 'Wrong password');
207
+                return false;
208
+            }
209
+        } else {
210
+            // not authenticated ?
211
+            if ( ! $this->session->exists('public_link_authenticated')
212
+                || $this->session->get('public_link_authenticated') !== (string)$share->getId()) {
213
+                return false;
214
+            }
215
+        }
216
+        return true;
217
+    }
218
+
219
+    /**
220
+     * throws hooks when a share is attempted to be accessed
221
+     *
222
+     * @param \OCP\Share\IShare|string $share the Share instance if available,
223
+     * otherwise token
224
+     * @param int $errorCode
225
+     * @param string $errorMessage
226
+     * @throws \OC\HintException
227
+     * @throws \OC\ServerNotAvailableException
228
+     */
229
+    protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
230
+        $itemType = $itemSource = $uidOwner = '';
231
+        $token = $share;
232
+        $exception = null;
233
+        if($share instanceof \OCP\Share\IShare) {
234
+            try {
235
+                $token = $share->getToken();
236
+                $uidOwner = $share->getSharedBy();
237
+                $itemType = $share->getNodeType();
238
+                $itemSource = $share->getNodeId();
239
+            } catch (\Exception $e) {
240
+                // we log what we know and pass on the exception afterwards
241
+                $exception = $e;
242
+            }
243
+        }
244
+        \OC_Hook::emit('OCP\Share', 'share_link_access', [
245
+            'itemType' => $itemType,
246
+            'itemSource' => $itemSource,
247
+            'uidOwner' => $uidOwner,
248
+            'token' => $token,
249
+            'errorCode' => $errorCode,
250
+            'errorMessage' => $errorMessage,
251
+        ]);
252
+        if(!is_null($exception)) {
253
+            throw $exception;
254
+        }
255
+    }
256
+
257
+    /**
258
+     * Validate the permissions of the share
259
+     *
260
+     * @param Share\IShare $share
261
+     * @return bool
262
+     */
263
+    private function validateShare(\OCP\Share\IShare $share) {
264
+        return $share->getNode()->isReadable() && $share->getNode()->isShareable();
265
+    }
266
+
267
+    /**
268
+     * @PublicPage
269
+     * @NoCSRFRequired
270
+     *
271
+     * @param string $token
272
+     * @param string $path
273
+     * @return TemplateResponse|RedirectResponse|NotFoundResponse
274
+     * @throws NotFoundException
275
+     * @throws \Exception
276
+     */
277
+    public function showShare($token, $path = '') {
278
+        \OC_User::setIncognitoMode(true);
279
+
280
+        // Check whether share exists
281
+        try {
282
+            $share = $this->shareManager->getShareByToken($token);
283
+        } catch (ShareNotFound $e) {
284
+            $this->emitAccessShareHook($token, 404, 'Share not found');
285
+            return new NotFoundResponse();
286
+        }
287
+
288
+        // Share is password protected - check whether the user is permitted to access the share
289
+        if ($share->getPassword() !== null && !$this->linkShareAuth($share)) {
290
+            return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate',
291
+                array('token' => $token)));
292
+        }
293
+
294
+        if (!$this->validateShare($share)) {
295
+            throw new NotFoundException();
296
+        }
297
+        // We can't get the path of a file share
298
+        try {
299
+            if ($share->getNode() instanceof \OCP\Files\File && $path !== '') {
300
+                $this->emitAccessShareHook($share, 404, 'Share not found');
301
+                throw new NotFoundException();
302
+            }
303
+        } catch (\Exception $e) {
304
+            $this->emitAccessShareHook($share, 404, 'Share not found');
305
+            throw $e;
306
+        }
307
+
308
+        $shareTmpl = [];
309
+        $shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
310
+        $shareTmpl['owner'] = $share->getShareOwner();
311
+        $shareTmpl['filename'] = $share->getNode()->getName();
312
+        $shareTmpl['directory_path'] = $share->getTarget();
313
+        $shareTmpl['mimetype'] = $share->getNode()->getMimetype();
314
+        $shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($share->getNode()->getMimetype());
315
+        $shareTmpl['dirToken'] = $token;
316
+        $shareTmpl['sharingToken'] = $token;
317
+        $shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
318
+        $shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
319
+        $shareTmpl['dir'] = '';
320
+        $shareTmpl['nonHumanFileSize'] = $share->getNode()->getSize();
321
+        $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($share->getNode()->getSize());
322
+
323
+        // Show file list
324
+        $hideFileList = false;
325
+        if ($share->getNode() instanceof \OCP\Files\Folder) {
326
+            /** @var \OCP\Files\Folder $rootFolder */
327
+            $rootFolder = $share->getNode();
328
+
329
+            try {
330
+                $folderNode = $rootFolder->get($path);
331
+            } catch (\OCP\Files\NotFoundException $e) {
332
+                $this->emitAccessShareHook($share, 404, 'Share not found');
333
+                throw new NotFoundException();
334
+            }
335
+
336
+            $shareTmpl['dir'] = $rootFolder->getRelativePath($folderNode->getPath());
337
+
338
+            /*
339 339
 			 * The OC_Util methods require a view. This just uses the node API
340 340
 			 */
341
-			$freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
342
-			if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
343
-				$freeSpace = max($freeSpace, 0);
344
-			} else {
345
-				$freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
346
-			}
347
-
348
-			$hideFileList = $share->getPermissions() & \OCP\Constants::PERMISSION_READ ? false : true;
349
-			$maxUploadFilesize = $freeSpace;
350
-
351
-			$folder = new Template('files', 'list', '');
352
-			$folder->assign('dir', $rootFolder->getRelativePath($folderNode->getPath()));
353
-			$folder->assign('dirToken', $token);
354
-			$folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
355
-			$folder->assign('isPublic', true);
356
-			$folder->assign('hideFileList', $hideFileList);
357
-			$folder->assign('publicUploadEnabled', 'no');
358
-			$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
359
-			$folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
360
-			$folder->assign('freeSpace', $freeSpace);
361
-			$folder->assign('usedSpacePercent', 0);
362
-			$folder->assign('trash', false);
363
-			$shareTmpl['folder'] = $folder->fetchPage();
364
-		}
365
-
366
-		$shareTmpl['hideFileList'] = $hideFileList;
367
-		$shareTmpl['shareOwner'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
368
-		$shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', ['token' => $token]);
369
-		$shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $token]);
370
-		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
371
-		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
372
-		$shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
373
-		$shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
374
-		$shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
375
-		$shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
376
-		if ($shareTmpl['previewSupported']) {
377
-			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute( 'files_sharing.PublicPreview.getPreview',
378
-				['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 't' => $shareTmpl['dirToken']]);
379
-			// We just have direct previews for image files
380
-			if ($share->getNode()->getMimePart() === 'image') {
381
-				$shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $token]);
382
-			}
383
-		} else {
384
-			$shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
385
-		}
386
-
387
-		// Load files we need
388
-		\OCP\Util::addScript('files', 'file-upload');
389
-		\OCP\Util::addStyle('files_sharing', 'publicView');
390
-		\OCP\Util::addScript('files_sharing', 'public');
391
-		\OCP\Util::addScript('files', 'fileactions');
392
-		\OCP\Util::addScript('files', 'fileactionsmenu');
393
-		\OCP\Util::addScript('files', 'jquery.fileupload');
394
-		\OCP\Util::addScript('files_sharing', 'files_drop');
395
-
396
-		if (isset($shareTmpl['folder'])) {
397
-			// JS required for folders
398
-			\OCP\Util::addStyle('files', 'merged');
399
-			\OCP\Util::addScript('files', 'filesummary');
400
-			\OCP\Util::addScript('files', 'breadcrumb');
401
-			\OCP\Util::addScript('files', 'fileinfomodel');
402
-			\OCP\Util::addScript('files', 'newfilemenu');
403
-			\OCP\Util::addScript('files', 'files');
404
-			\OCP\Util::addScript('files', 'filelist');
405
-			\OCP\Util::addScript('files', 'keyboardshortcuts');
406
-		}
407
-
408
-		// OpenGraph Support: http://ogp.me/
409
-		\OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
410
-		\OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->l10n->t('%s is publicly shared', [$shareTmpl['filename']])]);
411
-		\OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
412
-		\OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
413
-		\OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
414
-		\OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $shareTmpl['previewImage']]);
415
-
416
-		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts');
417
-
418
-		$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
419
-		$csp->addAllowedFrameDomain('\'self\'');
420
-		$response = new TemplateResponse($this->appName, 'public', $shareTmpl, 'base');
421
-		$response->setContentSecurityPolicy($csp);
422
-
423
-		$this->emitAccessShareHook($share);
424
-
425
-		return $response;
426
-	}
427
-
428
-	/**
429
-	 * @PublicPage
430
-	 * @NoCSRFRequired
431
-	 *
432
-	 * @param string $token
433
-	 * @param string $files
434
-	 * @param string $path
435
-	 * @param string $downloadStartSecret
436
-	 * @return void|\OCP\AppFramework\Http\Response
437
-	 * @throws NotFoundException
438
-	 */
439
-	public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
440
-		\OC_User::setIncognitoMode(true);
441
-
442
-		$share = $this->shareManager->getShareByToken($token);
443
-
444
-		if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
445
-			return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
446
-		}
447
-
448
-		// Share is password protected - check whether the user is permitted to access the share
449
-		if ($share->getPassword() !== null && !$this->linkShareAuth($share)) {
450
-			return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate',
451
-				['token' => $token]));
452
-		}
453
-
454
-		$files_list = null;
455
-		if (!is_null($files)) { // download selected files
456
-			$files_list = json_decode($files);
457
-			// in case we get only a single file
458
-			if ($files_list === null) {
459
-				$files_list = [$files];
460
-			}
461
-		}
462
-
463
-		$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
464
-		$originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
465
-
466
-		if (!$this->validateShare($share)) {
467
-			throw new NotFoundException();
468
-		}
469
-
470
-		// Single file share
471
-		if ($share->getNode() instanceof \OCP\Files\File) {
472
-			// Single file download
473
-			$this->singleFileDownloaded($share, $share->getNode());
474
-		}
475
-		// Directory share
476
-		else {
477
-			/** @var \OCP\Files\Folder $node */
478
-			$node = $share->getNode();
479
-
480
-			// Try to get the path
481
-			if ($path !== '') {
482
-				try {
483
-					$node = $node->get($path);
484
-				} catch (NotFoundException $e) {
485
-					$this->emitAccessShareHook($share, 404, 'Share not found');
486
-					return new NotFoundResponse();
487
-				}
488
-			}
489
-
490
-			$originalSharePath = $userFolder->getRelativePath($node->getPath());
491
-
492
-			if ($node instanceof \OCP\Files\File) {
493
-				// Single file download
494
-				$this->singleFileDownloaded($share, $share->getNode());
495
-			} else if (!empty($files_list)) {
496
-				$this->fileListDownloaded($share, $files_list, $node);
497
-			} else {
498
-				// The folder is downloaded
499
-				$this->singleFileDownloaded($share, $share->getNode());
500
-			}
501
-		}
502
-
503
-		/* FIXME: We should do this all nicely in OCP */
504
-		OC_Util::tearDownFS();
505
-		OC_Util::setupFS($share->getShareOwner());
506
-
507
-		/**
508
-		 * this sets a cookie to be able to recognize the start of the download
509
-		 * the content must not be longer than 32 characters and must only contain
510
-		 * alphanumeric characters
511
-		 */
512
-		if (!empty($downloadStartSecret)
513
-			&& !isset($downloadStartSecret[32])
514
-			&& preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
515
-
516
-			// FIXME: set on the response once we use an actual app framework response
517
-			setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
518
-		}
519
-
520
-		$this->emitAccessShareHook($share);
521
-
522
-		$server_params = array( 'head' => $this->request->getMethod() === 'HEAD' );
523
-
524
-		/**
525
-		 * Http range requests support
526
-		 */
527
-		if (isset($_SERVER['HTTP_RANGE'])) {
528
-			$server_params['range'] = $this->request->getHeader('Range');
529
-		}
530
-
531
-		// download selected files
532
-		if (!is_null($files) && $files !== '') {
533
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
534
-			// after dispatching the request which results in a "Cannot modify header information" notice.
535
-			OC_Files::get($originalSharePath, $files_list, $server_params);
536
-			exit();
537
-		} else {
538
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
539
-			// after dispatching the request which results in a "Cannot modify header information" notice.
540
-			OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
541
-			exit();
542
-		}
543
-	}
544
-
545
-	/**
546
-	 * create activity for every downloaded file
547
-	 *
548
-	 * @param Share\IShare $share
549
-	 * @param array $files_list
550
-	 * @param \OCP\Files\Folder $node
551
-	 */
552
-	protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
553
-		foreach ($files_list as $file) {
554
-			$subNode = $node->get($file);
555
-			$this->singleFileDownloaded($share, $subNode);
556
-		}
557
-
558
-	}
559
-
560
-	/**
561
-	 * create activity if a single file was downloaded from a link share
562
-	 *
563
-	 * @param Share\IShare $share
564
-	 */
565
-	protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
566
-
567
-		$fileId = $node->getId();
568
-
569
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
570
-		$userNodeList = $userFolder->getById($fileId);
571
-		$userNode = $userNodeList[0];
572
-		$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
573
-		$userPath = $userFolder->getRelativePath($userNode->getPath());
574
-		$ownerPath = $ownerFolder->getRelativePath($node->getPath());
575
-
576
-		$parameters = [$userPath];
577
-
578
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
579
-			if ($node instanceof \OCP\Files\File) {
580
-				$subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
581
-			} else {
582
-				$subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
583
-			}
584
-			$parameters[] = $share->getSharedWith();
585
-		} else {
586
-			if ($node instanceof \OCP\Files\File) {
587
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
588
-			} else {
589
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
590
-			}
591
-		}
592
-
593
-		$this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
594
-
595
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
596
-			$parameters[0] = $ownerPath;
597
-			$this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
598
-		}
599
-	}
600
-
601
-	/**
602
-	 * publish activity
603
-	 *
604
-	 * @param string $subject
605
-	 * @param array $parameters
606
-	 * @param string $affectedUser
607
-	 * @param int $fileId
608
-	 * @param string $filePath
609
-	 */
610
-	protected function publishActivity($subject,
611
-										array $parameters,
612
-										$affectedUser,
613
-										$fileId,
614
-										$filePath) {
615
-
616
-		$event = $this->activityManager->generateEvent();
617
-		$event->setApp('files_sharing')
618
-			->setType('public_links')
619
-			->setSubject($subject, $parameters)
620
-			->setAffectedUser($affectedUser)
621
-			->setObject('files', $fileId, $filePath);
622
-		$this->activityManager->publish($event);
623
-	}
341
+            $freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
342
+            if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
343
+                $freeSpace = max($freeSpace, 0);
344
+            } else {
345
+                $freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
346
+            }
347
+
348
+            $hideFileList = $share->getPermissions() & \OCP\Constants::PERMISSION_READ ? false : true;
349
+            $maxUploadFilesize = $freeSpace;
350
+
351
+            $folder = new Template('files', 'list', '');
352
+            $folder->assign('dir', $rootFolder->getRelativePath($folderNode->getPath()));
353
+            $folder->assign('dirToken', $token);
354
+            $folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
355
+            $folder->assign('isPublic', true);
356
+            $folder->assign('hideFileList', $hideFileList);
357
+            $folder->assign('publicUploadEnabled', 'no');
358
+            $folder->assign('uploadMaxFilesize', $maxUploadFilesize);
359
+            $folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
360
+            $folder->assign('freeSpace', $freeSpace);
361
+            $folder->assign('usedSpacePercent', 0);
362
+            $folder->assign('trash', false);
363
+            $shareTmpl['folder'] = $folder->fetchPage();
364
+        }
365
+
366
+        $shareTmpl['hideFileList'] = $hideFileList;
367
+        $shareTmpl['shareOwner'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
368
+        $shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', ['token' => $token]);
369
+        $shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $token]);
370
+        $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
371
+        $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
372
+        $shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
373
+        $shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
374
+        $shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
375
+        $shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
376
+        if ($shareTmpl['previewSupported']) {
377
+            $shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute( 'files_sharing.PublicPreview.getPreview',
378
+                ['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 't' => $shareTmpl['dirToken']]);
379
+            // We just have direct previews for image files
380
+            if ($share->getNode()->getMimePart() === 'image') {
381
+                $shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $token]);
382
+            }
383
+        } else {
384
+            $shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
385
+        }
386
+
387
+        // Load files we need
388
+        \OCP\Util::addScript('files', 'file-upload');
389
+        \OCP\Util::addStyle('files_sharing', 'publicView');
390
+        \OCP\Util::addScript('files_sharing', 'public');
391
+        \OCP\Util::addScript('files', 'fileactions');
392
+        \OCP\Util::addScript('files', 'fileactionsmenu');
393
+        \OCP\Util::addScript('files', 'jquery.fileupload');
394
+        \OCP\Util::addScript('files_sharing', 'files_drop');
395
+
396
+        if (isset($shareTmpl['folder'])) {
397
+            // JS required for folders
398
+            \OCP\Util::addStyle('files', 'merged');
399
+            \OCP\Util::addScript('files', 'filesummary');
400
+            \OCP\Util::addScript('files', 'breadcrumb');
401
+            \OCP\Util::addScript('files', 'fileinfomodel');
402
+            \OCP\Util::addScript('files', 'newfilemenu');
403
+            \OCP\Util::addScript('files', 'files');
404
+            \OCP\Util::addScript('files', 'filelist');
405
+            \OCP\Util::addScript('files', 'keyboardshortcuts');
406
+        }
407
+
408
+        // OpenGraph Support: http://ogp.me/
409
+        \OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
410
+        \OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->l10n->t('%s is publicly shared', [$shareTmpl['filename']])]);
411
+        \OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
412
+        \OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
413
+        \OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
414
+        \OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $shareTmpl['previewImage']]);
415
+
416
+        $this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts');
417
+
418
+        $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
419
+        $csp->addAllowedFrameDomain('\'self\'');
420
+        $response = new TemplateResponse($this->appName, 'public', $shareTmpl, 'base');
421
+        $response->setContentSecurityPolicy($csp);
422
+
423
+        $this->emitAccessShareHook($share);
424
+
425
+        return $response;
426
+    }
427
+
428
+    /**
429
+     * @PublicPage
430
+     * @NoCSRFRequired
431
+     *
432
+     * @param string $token
433
+     * @param string $files
434
+     * @param string $path
435
+     * @param string $downloadStartSecret
436
+     * @return void|\OCP\AppFramework\Http\Response
437
+     * @throws NotFoundException
438
+     */
439
+    public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
440
+        \OC_User::setIncognitoMode(true);
441
+
442
+        $share = $this->shareManager->getShareByToken($token);
443
+
444
+        if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
445
+            return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
446
+        }
447
+
448
+        // Share is password protected - check whether the user is permitted to access the share
449
+        if ($share->getPassword() !== null && !$this->linkShareAuth($share)) {
450
+            return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate',
451
+                ['token' => $token]));
452
+        }
453
+
454
+        $files_list = null;
455
+        if (!is_null($files)) { // download selected files
456
+            $files_list = json_decode($files);
457
+            // in case we get only a single file
458
+            if ($files_list === null) {
459
+                $files_list = [$files];
460
+            }
461
+        }
462
+
463
+        $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
464
+        $originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
465
+
466
+        if (!$this->validateShare($share)) {
467
+            throw new NotFoundException();
468
+        }
469
+
470
+        // Single file share
471
+        if ($share->getNode() instanceof \OCP\Files\File) {
472
+            // Single file download
473
+            $this->singleFileDownloaded($share, $share->getNode());
474
+        }
475
+        // Directory share
476
+        else {
477
+            /** @var \OCP\Files\Folder $node */
478
+            $node = $share->getNode();
479
+
480
+            // Try to get the path
481
+            if ($path !== '') {
482
+                try {
483
+                    $node = $node->get($path);
484
+                } catch (NotFoundException $e) {
485
+                    $this->emitAccessShareHook($share, 404, 'Share not found');
486
+                    return new NotFoundResponse();
487
+                }
488
+            }
489
+
490
+            $originalSharePath = $userFolder->getRelativePath($node->getPath());
491
+
492
+            if ($node instanceof \OCP\Files\File) {
493
+                // Single file download
494
+                $this->singleFileDownloaded($share, $share->getNode());
495
+            } else if (!empty($files_list)) {
496
+                $this->fileListDownloaded($share, $files_list, $node);
497
+            } else {
498
+                // The folder is downloaded
499
+                $this->singleFileDownloaded($share, $share->getNode());
500
+            }
501
+        }
502
+
503
+        /* FIXME: We should do this all nicely in OCP */
504
+        OC_Util::tearDownFS();
505
+        OC_Util::setupFS($share->getShareOwner());
506
+
507
+        /**
508
+         * this sets a cookie to be able to recognize the start of the download
509
+         * the content must not be longer than 32 characters and must only contain
510
+         * alphanumeric characters
511
+         */
512
+        if (!empty($downloadStartSecret)
513
+            && !isset($downloadStartSecret[32])
514
+            && preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
515
+
516
+            // FIXME: set on the response once we use an actual app framework response
517
+            setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
518
+        }
519
+
520
+        $this->emitAccessShareHook($share);
521
+
522
+        $server_params = array( 'head' => $this->request->getMethod() === 'HEAD' );
523
+
524
+        /**
525
+         * Http range requests support
526
+         */
527
+        if (isset($_SERVER['HTTP_RANGE'])) {
528
+            $server_params['range'] = $this->request->getHeader('Range');
529
+        }
530
+
531
+        // download selected files
532
+        if (!is_null($files) && $files !== '') {
533
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
534
+            // after dispatching the request which results in a "Cannot modify header information" notice.
535
+            OC_Files::get($originalSharePath, $files_list, $server_params);
536
+            exit();
537
+        } else {
538
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
539
+            // after dispatching the request which results in a "Cannot modify header information" notice.
540
+            OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
541
+            exit();
542
+        }
543
+    }
544
+
545
+    /**
546
+     * create activity for every downloaded file
547
+     *
548
+     * @param Share\IShare $share
549
+     * @param array $files_list
550
+     * @param \OCP\Files\Folder $node
551
+     */
552
+    protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
553
+        foreach ($files_list as $file) {
554
+            $subNode = $node->get($file);
555
+            $this->singleFileDownloaded($share, $subNode);
556
+        }
557
+
558
+    }
559
+
560
+    /**
561
+     * create activity if a single file was downloaded from a link share
562
+     *
563
+     * @param Share\IShare $share
564
+     */
565
+    protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
566
+
567
+        $fileId = $node->getId();
568
+
569
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
570
+        $userNodeList = $userFolder->getById($fileId);
571
+        $userNode = $userNodeList[0];
572
+        $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
573
+        $userPath = $userFolder->getRelativePath($userNode->getPath());
574
+        $ownerPath = $ownerFolder->getRelativePath($node->getPath());
575
+
576
+        $parameters = [$userPath];
577
+
578
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
579
+            if ($node instanceof \OCP\Files\File) {
580
+                $subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
581
+            } else {
582
+                $subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
583
+            }
584
+            $parameters[] = $share->getSharedWith();
585
+        } else {
586
+            if ($node instanceof \OCP\Files\File) {
587
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
588
+            } else {
589
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
590
+            }
591
+        }
592
+
593
+        $this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
594
+
595
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
596
+            $parameters[0] = $ownerPath;
597
+            $this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
598
+        }
599
+    }
600
+
601
+    /**
602
+     * publish activity
603
+     *
604
+     * @param string $subject
605
+     * @param array $parameters
606
+     * @param string $affectedUser
607
+     * @param int $fileId
608
+     * @param string $filePath
609
+     */
610
+    protected function publishActivity($subject,
611
+                                        array $parameters,
612
+                                        $affectedUser,
613
+                                        $fileId,
614
+                                        $filePath) {
615
+
616
+        $event = $this->activityManager->generateEvent();
617
+        $event->setApp('files_sharing')
618
+            ->setType('public_links')
619
+            ->setSubject($subject, $parameters)
620
+            ->setAffectedUser($affectedUser)
621
+            ->setObject('files', $fileId, $filePath);
622
+        $this->activityManager->publish($event);
623
+    }
624 624
 
625 625
 
626 626
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -150,7 +150,7 @@  discard block
 block discarded – undo
150 150
 	public function showAuthenticate($token) {
151 151
 		$share = $this->shareManager->getShareByToken($token);
152 152
 
153
-		if($this->linkShareAuth($share)) {
153
+		if ($this->linkShareAuth($share)) {
154 154
 			return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token)));
155 155
 		}
156 156
 
@@ -178,7 +178,7 @@  discard block
 block discarded – undo
178 178
 
179 179
 		$authenticate = $this->linkShareAuth($share, $password);
180 180
 
181
-		if($authenticate === true) {
181
+		if ($authenticate === true) {
182 182
 			return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token)));
183 183
 		}
184 184
 
@@ -201,15 +201,15 @@  discard block
 block discarded – undo
201 201
 	private function linkShareAuth(\OCP\Share\IShare $share, $password = null) {
202 202
 		if ($password !== null) {
203 203
 			if ($this->shareManager->checkPassword($share, $password)) {
204
-				$this->session->set('public_link_authenticated', (string)$share->getId());
204
+				$this->session->set('public_link_authenticated', (string) $share->getId());
205 205
 			} else {
206 206
 				$this->emitAccessShareHook($share, 403, 'Wrong password');
207 207
 				return false;
208 208
 			}
209 209
 		} else {
210 210
 			// not authenticated ?
211
-			if ( ! $this->session->exists('public_link_authenticated')
212
-				|| $this->session->get('public_link_authenticated') !== (string)$share->getId()) {
211
+			if (!$this->session->exists('public_link_authenticated')
212
+				|| $this->session->get('public_link_authenticated') !== (string) $share->getId()) {
213 213
 				return false;
214 214
 			}
215 215
 		}
@@ -230,7 +230,7 @@  discard block
 block discarded – undo
230 230
 		$itemType = $itemSource = $uidOwner = '';
231 231
 		$token = $share;
232 232
 		$exception = null;
233
-		if($share instanceof \OCP\Share\IShare) {
233
+		if ($share instanceof \OCP\Share\IShare) {
234 234
 			try {
235 235
 				$token = $share->getToken();
236 236
 				$uidOwner = $share->getSharedBy();
@@ -249,7 +249,7 @@  discard block
 block discarded – undo
249 249
 			'errorCode' => $errorCode,
250 250
 			'errorMessage' => $errorMessage,
251 251
 		]);
252
-		if(!is_null($exception)) {
252
+		if (!is_null($exception)) {
253 253
 			throw $exception;
254 254
 		}
255 255
 	}
@@ -374,7 +374,7 @@  discard block
 block discarded – undo
374 374
 		$shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
375 375
 		$shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
376 376
 		if ($shareTmpl['previewSupported']) {
377
-			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute( 'files_sharing.PublicPreview.getPreview',
377
+			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview',
378 378
 				['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 't' => $shareTmpl['dirToken']]);
379 379
 			// We just have direct previews for image files
380 380
 			if ($share->getNode()->getMimePart() === 'image') {
@@ -406,7 +406,7 @@  discard block
 block discarded – undo
406 406
 		}
407 407
 
408 408
 		// OpenGraph Support: http://ogp.me/
409
-		\OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
409
+		\OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $this->defaults->getName().($this->defaults->getSlogan() !== '' ? ' - '.$this->defaults->getSlogan() : '')]);
410 410
 		\OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->l10n->t('%s is publicly shared', [$shareTmpl['filename']])]);
411 411
 		\OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
412 412
 		\OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
@@ -441,7 +441,7 @@  discard block
 block discarded – undo
441 441
 
442 442
 		$share = $this->shareManager->getShareByToken($token);
443 443
 
444
-		if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
444
+		if (!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
445 445
 			return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
446 446
 		}
447 447
 
@@ -519,7 +519,7 @@  discard block
 block discarded – undo
519 519
 
520 520
 		$this->emitAccessShareHook($share);
521 521
 
522
-		$server_params = array( 'head' => $this->request->getMethod() === 'HEAD' );
522
+		$server_params = array('head' => $this->request->getMethod() === 'HEAD');
523 523
 
524 524
 		/**
525 525
 		 * Http range requests support
Please login to merge, or discard this patch.
apps/provisioning_api/lib/Controller/UsersController.php 4 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -225,7 +225,7 @@
 block discarded – undo
225 225
 	/**
226 226
 	 * creates a array with all user data
227 227
 	 *
228
-	 * @param $userId
228
+	 * @param string $userId
229 229
 	 * @return array
230 230
 	 * @throws OCSException
231 231
 	 */
Please login to merge, or discard this patch.
Braces   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -335,7 +335,7 @@
 block discarded – undo
335 335
 					}
336 336
 					if($quota === 0) {
337 337
 						$quota = 'default';
338
-					}else if($quota === -1) {
338
+					} else if($quota === -1) {
339 339
 						$quota = 'none';
340 340
 					} else {
341 341
 						$quota = \OCP\Util::humanFileSize($quota);
Please login to merge, or discard this patch.
Indentation   +782 added lines, -782 removed lines patch added patch discarded remove patch
@@ -49,786 +49,786 @@
 block discarded – undo
49 49
 
50 50
 class UsersController extends OCSController {
51 51
 
52
-	/** @var IUserManager */
53
-	private $userManager;
54
-	/** @var IConfig */
55
-	private $config;
56
-	/** @var IAppManager */
57
-	private $appManager;
58
-	/** @var IGroupManager|\OC\Group\Manager */ // FIXME Requires a method that is not on the interface
59
-	private $groupManager;
60
-	/** @var IUserSession */
61
-	private $userSession;
62
-	/** @var AccountManager */
63
-	private $accountManager;
64
-	/** @var ILogger */
65
-	private $logger;
66
-	/** @var IFactory */
67
-	private $l10nFactory;
68
-	/** @var NewUserMailHelper */
69
-	private $newUserMailHelper;
70
-
71
-	/**
72
-	 * @param string $appName
73
-	 * @param IRequest $request
74
-	 * @param IUserManager $userManager
75
-	 * @param IConfig $config
76
-	 * @param IAppManager $appManager
77
-	 * @param IGroupManager $groupManager
78
-	 * @param IUserSession $userSession
79
-	 * @param AccountManager $accountManager
80
-	 * @param ILogger $logger
81
-	 * @param IFactory $l10nFactory
82
-	 * @param NewUserMailHelper $newUserMailHelper
83
-	 */
84
-	public function __construct($appName,
85
-								IRequest $request,
86
-								IUserManager $userManager,
87
-								IConfig $config,
88
-								IAppManager $appManager,
89
-								IGroupManager $groupManager,
90
-								IUserSession $userSession,
91
-								AccountManager $accountManager,
92
-								ILogger $logger,
93
-								IFactory $l10nFactory,
94
-								NewUserMailHelper $newUserMailHelper) {
95
-		parent::__construct($appName, $request);
96
-
97
-		$this->userManager = $userManager;
98
-		$this->config = $config;
99
-		$this->appManager = $appManager;
100
-		$this->groupManager = $groupManager;
101
-		$this->userSession = $userSession;
102
-		$this->accountManager = $accountManager;
103
-		$this->logger = $logger;
104
-		$this->l10nFactory = $l10nFactory;
105
-		$this->newUserMailHelper = $newUserMailHelper;
106
-	}
107
-
108
-	/**
109
-	 * @NoAdminRequired
110
-	 *
111
-	 * returns a list of users
112
-	 *
113
-	 * @param string $search
114
-	 * @param int $limit
115
-	 * @param int $offset
116
-	 * @return DataResponse
117
-	 */
118
-	public function getUsers($search = '', $limit = null, $offset = null) {
119
-		$user = $this->userSession->getUser();
120
-		$users = [];
121
-
122
-		// Admin? Or SubAdmin?
123
-		$uid = $user->getUID();
124
-		$subAdminManager = $this->groupManager->getSubAdmin();
125
-		if($this->groupManager->isAdmin($uid)){
126
-			$users = $this->userManager->search($search, $limit, $offset);
127
-		} else if ($subAdminManager->isSubAdmin($user)) {
128
-			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
129
-			foreach ($subAdminOfGroups as $key => $group) {
130
-				$subAdminOfGroups[$key] = $group->getGID();
131
-			}
132
-
133
-			if($offset === null) {
134
-				$offset = 0;
135
-			}
136
-
137
-			$users = [];
138
-			foreach ($subAdminOfGroups as $group) {
139
-				$users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search));
140
-			}
141
-
142
-			$users = array_slice($users, $offset, $limit);
143
-		}
144
-
145
-		$users = array_keys($users);
146
-
147
-		return new DataResponse([
148
-			'users' => $users
149
-		]);
150
-	}
151
-
152
-	/**
153
-	 * @PasswordConfirmationRequired
154
-	 * @NoAdminRequired
155
-	 *
156
-	 * @param string $userid
157
-	 * @param string $password
158
-	 * @param array $groups
159
-	 * @return DataResponse
160
-	 * @throws OCSException
161
-	 */
162
-	public function addUser($userid, $password, $groups = null) {
163
-		$user = $this->userSession->getUser();
164
-		$isAdmin = $this->groupManager->isAdmin($user->getUID());
165
-		$subAdminManager = $this->groupManager->getSubAdmin();
166
-
167
-		if($this->userManager->userExists($userid)) {
168
-			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
169
-			throw new OCSException('User already exists', 102);
170
-		}
171
-
172
-		if(is_array($groups)) {
173
-			foreach ($groups as $group) {
174
-				if(!$this->groupManager->groupExists($group)) {
175
-					throw new OCSException('group '.$group.' does not exist', 104);
176
-				}
177
-				if(!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) {
178
-					throw new OCSException('insufficient privileges for group '. $group, 105);
179
-				}
180
-			}
181
-		} else {
182
-			if(!$isAdmin) {
183
-				throw new OCSException('no group specified (required for subadmins)', 106);
184
-			}
185
-		}
186
-
187
-		try {
188
-			$newUser = $this->userManager->createUser($userid, $password);
189
-			$this->logger->info('Successful addUser call with userid: '.$userid, ['app' => 'ocs_api']);
190
-
191
-			if (is_array($groups)) {
192
-				foreach ($groups as $group) {
193
-					$this->groupManager->get($group)->addUser($newUser);
194
-					$this->logger->info('Added userid '.$userid.' to group '.$group, ['app' => 'ocs_api']);
195
-				}
196
-			}
197
-			return new DataResponse();
198
-		} catch (\Exception $e) {
199
-			$this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
200
-			throw new OCSException('Bad request', 101);
201
-		}
202
-	}
203
-
204
-	/**
205
-	 * @NoAdminRequired
206
-	 * @NoSubAdminRequired
207
-	 *
208
-	 * gets user info
209
-	 *
210
-	 * @param string $userId
211
-	 * @return DataResponse
212
-	 * @throws OCSException
213
-	 */
214
-	public function getUser($userId) {
215
-		$data = $this->getUserData($userId);
216
-		return new DataResponse($data);
217
-	}
218
-
219
-	/**
220
-	 * @NoAdminRequired
221
-	 * @NoSubAdminRequired
222
-	 *
223
-	 * gets user info from the currently logged in user
224
-	 *
225
-	 * @return DataResponse
226
-	 * @throws OCSException
227
-	 */
228
-	public function getCurrentUser() {
229
-		$user = $this->userSession->getUser();
230
-		if ($user) {
231
-			$data =  $this->getUserData($user->getUID());
232
-			// rename "displayname" to "display-name" only for this call to keep
233
-			// the API stable.
234
-			$data['display-name'] = $data['displayname'];
235
-			unset($data['displayname']);
236
-			return new DataResponse($data);
237
-
238
-		}
239
-
240
-		throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
241
-	}
242
-
243
-	/**
244
-	 * creates a array with all user data
245
-	 *
246
-	 * @param $userId
247
-	 * @return array
248
-	 * @throws OCSException
249
-	 */
250
-	protected function getUserData($userId) {
251
-		$currentLoggedInUser = $this->userSession->getUser();
252
-
253
-		$data = [];
254
-
255
-		// Check if the target user exists
256
-		$targetUserObject = $this->userManager->get($userId);
257
-		if($targetUserObject === null) {
258
-			throw new OCSException('The requested user could not be found', \OCP\API::RESPOND_NOT_FOUND);
259
-		}
260
-
261
-		// Admin? Or SubAdmin?
262
-		if($this->groupManager->isAdmin($currentLoggedInUser->getUID())
263
-			|| $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) {
264
-			$data['enabled'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'enabled', 'true');
265
-		} else {
266
-			// Check they are looking up themselves
267
-			if($currentLoggedInUser->getUID() !== $targetUserObject->getUID()) {
268
-				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
269
-			}
270
-		}
271
-
272
-		$userAccount = $this->accountManager->getUser($targetUserObject);
273
-		$groups = $this->groupManager->getUserGroups($targetUserObject);
274
-		$gids = [];
275
-		foreach ($groups as $group) {
276
-			$gids[] = $group->getDisplayName();
277
-		}
278
-
279
-		// Find the data
280
-		$data['id'] = $targetUserObject->getUID();
281
-		$data['quota'] = $this->fillStorageInfo($targetUserObject->getUID());
282
-		$data[AccountManager::PROPERTY_EMAIL] = $targetUserObject->getEMailAddress();
283
-		$data[AccountManager::PROPERTY_DISPLAYNAME] = $targetUserObject->getDisplayName();
284
-		$data[AccountManager::PROPERTY_PHONE] = $userAccount[AccountManager::PROPERTY_PHONE]['value'];
285
-		$data[AccountManager::PROPERTY_ADDRESS] = $userAccount[AccountManager::PROPERTY_ADDRESS]['value'];
286
-		$data[AccountManager::PROPERTY_WEBSITE] = $userAccount[AccountManager::PROPERTY_WEBSITE]['value'];
287
-		$data[AccountManager::PROPERTY_TWITTER] = $userAccount[AccountManager::PROPERTY_TWITTER]['value'];
288
-		$data['groups'] = $gids;
289
-		$data['language'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'lang');
290
-
291
-		return $data;
292
-	}
293
-
294
-	/**
295
-	 * @NoAdminRequired
296
-	 * @NoSubAdminRequired
297
-	 * @PasswordConfirmationRequired
298
-	 *
299
-	 * edit users
300
-	 *
301
-	 * @param string $userId
302
-	 * @param string $key
303
-	 * @param string $value
304
-	 * @return DataResponse
305
-	 * @throws OCSException
306
-	 * @throws OCSForbiddenException
307
-	 */
308
-	public function editUser($userId, $key, $value) {
309
-		$currentLoggedInUser = $this->userSession->getUser();
310
-
311
-		$targetUser = $this->userManager->get($userId);
312
-		if($targetUser === null) {
313
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
314
-		}
315
-
316
-		$permittedFields = [];
317
-		if($targetUser->getUID() === $currentLoggedInUser->getUID()) {
318
-			// Editing self (display, email)
319
-			if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
320
-				$permittedFields[] = 'display';
321
-				$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
322
-				$permittedFields[] = AccountManager::PROPERTY_EMAIL;
323
-			}
324
-
325
-			$permittedFields[] = 'password';
326
-			if ($this->config->getSystemValue('force_language', false) === false ||
327
-				$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
328
-				$permittedFields[] = 'language';
329
-			}
330
-
331
-			if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
332
-				$federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
333
-				$shareProvider = $federatedFileSharing->getFederatedShareProvider();
334
-				if ($shareProvider->isLookupServerUploadEnabled()) {
335
-					$permittedFields[] = AccountManager::PROPERTY_PHONE;
336
-					$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
337
-					$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
338
-					$permittedFields[] = AccountManager::PROPERTY_TWITTER;
339
-				}
340
-			}
341
-
342
-			// If admin they can edit their own quota
343
-			if($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
344
-				$permittedFields[] = 'quota';
345
-			}
346
-		} else {
347
-			// Check if admin / subadmin
348
-			$subAdminManager = $this->groupManager->getSubAdmin();
349
-			if($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
350
-			|| $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
351
-				// They have permissions over the user
352
-				$permittedFields[] = 'display';
353
-				$permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
354
-				$permittedFields[] = AccountManager::PROPERTY_EMAIL;
355
-				$permittedFields[] = 'password';
356
-				$permittedFields[] = 'language';
357
-				$permittedFields[] = AccountManager::PROPERTY_PHONE;
358
-				$permittedFields[] = AccountManager::PROPERTY_ADDRESS;
359
-				$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
360
-				$permittedFields[] = AccountManager::PROPERTY_TWITTER;
361
-				$permittedFields[] = 'quota';
362
-			} else {
363
-				// No rights
364
-				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
365
-			}
366
-		}
367
-		// Check if permitted to edit this field
368
-		if(!in_array($key, $permittedFields)) {
369
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
370
-		}
371
-		// Process the edit
372
-		switch($key) {
373
-			case 'display':
374
-			case AccountManager::PROPERTY_DISPLAYNAME:
375
-				$targetUser->setDisplayName($value);
376
-				break;
377
-			case 'quota':
378
-				$quota = $value;
379
-				if($quota !== 'none' && $quota !== 'default') {
380
-					if (is_numeric($quota)) {
381
-						$quota = (float) $quota;
382
-					} else {
383
-						$quota = \OCP\Util::computerFileSize($quota);
384
-					}
385
-					if ($quota === false) {
386
-						throw new OCSException('Invalid quota value '.$value, 103);
387
-					}
388
-					if($quota === 0) {
389
-						$quota = 'default';
390
-					}else if($quota === -1) {
391
-						$quota = 'none';
392
-					} else {
393
-						$quota = \OCP\Util::humanFileSize($quota);
394
-					}
395
-				}
396
-				$targetUser->setQuota($quota);
397
-				break;
398
-			case 'password':
399
-				$targetUser->setPassword($value);
400
-				break;
401
-			case 'language':
402
-				$languagesCodes = $this->l10nFactory->findAvailableLanguages();
403
-				if (!in_array($value, $languagesCodes, true) && $value !== 'en') {
404
-					throw new OCSException('Invalid language', 102);
405
-				}
406
-				$this->config->setUserValue($targetUser->getUID(), 'core', 'lang', $value);
407
-				break;
408
-			case AccountManager::PROPERTY_EMAIL:
409
-				if(filter_var($value, FILTER_VALIDATE_EMAIL)) {
410
-					$targetUser->setEMailAddress($value);
411
-				} else {
412
-					throw new OCSException('', 102);
413
-				}
414
-				break;
415
-			case AccountManager::PROPERTY_PHONE:
416
-			case AccountManager::PROPERTY_ADDRESS:
417
-			case AccountManager::PROPERTY_WEBSITE:
418
-			case AccountManager::PROPERTY_TWITTER:
419
-				$userAccount = $this->accountManager->getUser($targetUser);
420
-				if ($userAccount[$key]['value'] !== $value) {
421
-					$userAccount[$key]['value'] = $value;
422
-					$this->accountManager->updateUser($targetUser, $userAccount);
423
-				}
424
-				break;
425
-			default:
426
-				throw new OCSException('', 103);
427
-		}
428
-		return new DataResponse();
429
-	}
430
-
431
-	/**
432
-	 * @PasswordConfirmationRequired
433
-	 * @NoAdminRequired
434
-	 *
435
-	 * @param string $userId
436
-	 * @return DataResponse
437
-	 * @throws OCSException
438
-	 * @throws OCSForbiddenException
439
-	 */
440
-	public function deleteUser($userId) {
441
-		$currentLoggedInUser = $this->userSession->getUser();
442
-
443
-		$targetUser = $this->userManager->get($userId);
444
-
445
-		if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
446
-			throw new OCSException('', 101);
447
-		}
448
-
449
-		// If not permitted
450
-		$subAdminManager = $this->groupManager->getSubAdmin();
451
-		if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
452
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
453
-		}
454
-
455
-		// Go ahead with the delete
456
-		if($targetUser->delete()) {
457
-			return new DataResponse();
458
-		} else {
459
-			throw new OCSException('', 101);
460
-		}
461
-	}
462
-
463
-	/**
464
-	 * @PasswordConfirmationRequired
465
-	 * @NoAdminRequired
466
-	 *
467
-	 * @param string $userId
468
-	 * @return DataResponse
469
-	 * @throws OCSException
470
-	 * @throws OCSForbiddenException
471
-	 */
472
-	public function disableUser($userId) {
473
-		return $this->setEnabled($userId, false);
474
-	}
475
-
476
-	/**
477
-	 * @PasswordConfirmationRequired
478
-	 * @NoAdminRequired
479
-	 *
480
-	 * @param string $userId
481
-	 * @return DataResponse
482
-	 * @throws OCSException
483
-	 * @throws OCSForbiddenException
484
-	 */
485
-	public function enableUser($userId) {
486
-		return $this->setEnabled($userId, true);
487
-	}
488
-
489
-	/**
490
-	 * @param string $userId
491
-	 * @param bool $value
492
-	 * @return DataResponse
493
-	 * @throws OCSException
494
-	 * @throws OCSForbiddenException
495
-	 */
496
-	private function setEnabled($userId, $value) {
497
-		$currentLoggedInUser = $this->userSession->getUser();
498
-
499
-		$targetUser = $this->userManager->get($userId);
500
-		if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
501
-			throw new OCSException('', 101);
502
-		}
503
-
504
-		// If not permitted
505
-		$subAdminManager = $this->groupManager->getSubAdmin();
506
-		if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
507
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
508
-		}
509
-
510
-		// enable/disable the user now
511
-		$targetUser->setEnabled($value);
512
-		return new DataResponse();
513
-	}
514
-
515
-	/**
516
-	 * @NoAdminRequired
517
-	 * @NoSubAdminRequired
518
-	 *
519
-	 * @param string $userId
520
-	 * @return DataResponse
521
-	 * @throws OCSException
522
-	 */
523
-	public function getUsersGroups($userId) {
524
-		$loggedInUser = $this->userSession->getUser();
525
-
526
-		$targetUser = $this->userManager->get($userId);
527
-		if($targetUser === null) {
528
-			throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
529
-		}
530
-
531
-		if($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
532
-			// Self lookup or admin lookup
533
-			return new DataResponse([
534
-				'groups' => $this->groupManager->getUserGroupIds($targetUser)
535
-			]);
536
-		} else {
537
-			$subAdminManager = $this->groupManager->getSubAdmin();
538
-
539
-			// Looking up someone else
540
-			if($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
541
-				// Return the group that the method caller is subadmin of for the user in question
542
-				/** @var IGroup[] $getSubAdminsGroups */
543
-				$getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
544
-				foreach ($getSubAdminsGroups as $key => $group) {
545
-					$getSubAdminsGroups[$key] = $group->getGID();
546
-				}
547
-				$groups = array_intersect(
548
-					$getSubAdminsGroups,
549
-					$this->groupManager->getUserGroupIds($targetUser)
550
-				);
551
-				return new DataResponse(['groups' => $groups]);
552
-			} else {
553
-				// Not permitted
554
-				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
555
-			}
556
-		}
557
-
558
-	}
559
-
560
-	/**
561
-	 * @PasswordConfirmationRequired
562
-	 * @NoAdminRequired
563
-	 *
564
-	 * @param string $userId
565
-	 * @param string $groupid
566
-	 * @return DataResponse
567
-	 * @throws OCSException
568
-	 */
569
-	public function addToGroup($userId, $groupid = '') {
570
-		if($groupid === '') {
571
-			throw new OCSException('', 101);
572
-		}
573
-
574
-		$group = $this->groupManager->get($groupid);
575
-		$targetUser = $this->userManager->get($userId);
576
-		if($group === null) {
577
-			throw new OCSException('', 102);
578
-		}
579
-		if($targetUser === null) {
580
-			throw new OCSException('', 103);
581
-		}
582
-
583
-		// If they're not an admin, check they are a subadmin of the group in question
584
-		$loggedInUser = $this->userSession->getUser();
585
-		$subAdminManager = $this->groupManager->getSubAdmin();
586
-		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
587
-			throw new OCSException('', 104);
588
-		}
589
-
590
-		// Add user to group
591
-		$group->addUser($targetUser);
592
-		return new DataResponse();
593
-	}
594
-
595
-	/**
596
-	 * @PasswordConfirmationRequired
597
-	 * @NoAdminRequired
598
-	 *
599
-	 * @param string $userId
600
-	 * @param string $groupid
601
-	 * @return DataResponse
602
-	 * @throws OCSException
603
-	 */
604
-	public function removeFromGroup($userId, $groupid) {
605
-		$loggedInUser = $this->userSession->getUser();
606
-
607
-		if($groupid === null || trim($groupid) === '') {
608
-			throw new OCSException('', 101);
609
-		}
610
-
611
-		$group = $this->groupManager->get($groupid);
612
-		if($group === null) {
613
-			throw new OCSException('', 102);
614
-		}
615
-
616
-		$targetUser = $this->userManager->get($userId);
617
-		if($targetUser === null) {
618
-			throw new OCSException('', 103);
619
-		}
620
-
621
-		// If they're not an admin, check they are a subadmin of the group in question
622
-		$subAdminManager = $this->groupManager->getSubAdmin();
623
-		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
624
-			throw new OCSException('', 104);
625
-		}
626
-
627
-		// Check they aren't removing themselves from 'admin' or their 'subadmin; group
628
-		if ($targetUser->getUID() === $loggedInUser->getUID()) {
629
-			if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
630
-				if ($group->getGID() === 'admin') {
631
-					throw new OCSException('Cannot remove yourself from the admin group', 105);
632
-				}
633
-			} else {
634
-				// Not an admin, so the user must be a subadmin of this group, but that is not allowed.
635
-				throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
636
-			}
637
-
638
-		} else if (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
639
-			/** @var IGroup[] $subAdminGroups */
640
-			$subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
641
-			$subAdminGroups = array_map(function (IGroup $subAdminGroup) {
642
-				return $subAdminGroup->getGID();
643
-			}, $subAdminGroups);
644
-			$userGroups = $this->groupManager->getUserGroupIds($targetUser);
645
-			$userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
646
-
647
-			if (count($userSubAdminGroups) <= 1) {
648
-				// Subadmin must not be able to remove a user from all their subadmin groups.
649
-				throw new OCSException('Cannot remove user from this group as this is the only remaining group you are a SubAdmin of', 105);
650
-			}
651
-		}
652
-
653
-		// Remove user from group
654
-		$group->removeUser($targetUser);
655
-		return new DataResponse();
656
-	}
657
-
658
-	/**
659
-	 * Creates a subadmin
660
-	 *
661
-	 * @PasswordConfirmationRequired
662
-	 *
663
-	 * @param string $userId
664
-	 * @param string $groupid
665
-	 * @return DataResponse
666
-	 * @throws OCSException
667
-	 */
668
-	public function addSubAdmin($userId, $groupid) {
669
-		$group = $this->groupManager->get($groupid);
670
-		$user = $this->userManager->get($userId);
671
-
672
-		// Check if the user exists
673
-		if($user === null) {
674
-			throw new OCSException('User does not exist', 101);
675
-		}
676
-		// Check if group exists
677
-		if($group === null) {
678
-			throw new OCSException('Group does not exist',  102);
679
-		}
680
-		// Check if trying to make subadmin of admin group
681
-		if($group->getGID() === 'admin') {
682
-			throw new OCSException('Cannot create subadmins for admin group', 103);
683
-		}
684
-
685
-		$subAdminManager = $this->groupManager->getSubAdmin();
686
-
687
-		// We cannot be subadmin twice
688
-		if ($subAdminManager->isSubAdminofGroup($user, $group)) {
689
-			return new DataResponse();
690
-		}
691
-		// Go
692
-		if($subAdminManager->createSubAdmin($user, $group)) {
693
-			return new DataResponse();
694
-		} else {
695
-			throw new OCSException('Unknown error occurred', 103);
696
-		}
697
-	}
698
-
699
-	/**
700
-	 * Removes a subadmin from a group
701
-	 *
702
-	 * @PasswordConfirmationRequired
703
-	 *
704
-	 * @param string $userId
705
-	 * @param string $groupid
706
-	 * @return DataResponse
707
-	 * @throws OCSException
708
-	 */
709
-	public function removeSubAdmin($userId, $groupid) {
710
-		$group = $this->groupManager->get($groupid);
711
-		$user = $this->userManager->get($userId);
712
-		$subAdminManager = $this->groupManager->getSubAdmin();
713
-
714
-		// Check if the user exists
715
-		if($user === null) {
716
-			throw new OCSException('User does not exist', 101);
717
-		}
718
-		// Check if the group exists
719
-		if($group === null) {
720
-			throw new OCSException('Group does not exist', 101);
721
-		}
722
-		// Check if they are a subadmin of this said group
723
-		if(!$subAdminManager->isSubAdminOfGroup($user, $group)) {
724
-			throw new OCSException('User is not a subadmin of this group', 102);
725
-		}
726
-
727
-		// Go
728
-		if($subAdminManager->deleteSubAdmin($user, $group)) {
729
-			return new DataResponse();
730
-		} else {
731
-			throw new OCSException('Unknown error occurred', 103);
732
-		}
733
-	}
734
-
735
-	/**
736
-	 * Get the groups a user is a subadmin of
737
-	 *
738
-	 * @param string $userId
739
-	 * @return DataResponse
740
-	 * @throws OCSException
741
-	 */
742
-	public function getUserSubAdminGroups($userId) {
743
-		$user = $this->userManager->get($userId);
744
-		// Check if the user exists
745
-		if($user === null) {
746
-			throw new OCSException('User does not exist', 101);
747
-		}
748
-
749
-		// Get the subadmin groups
750
-		$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user);
751
-		foreach ($groups as $key => $group) {
752
-			$groups[$key] = $group->getGID();
753
-		}
754
-
755
-		if(!$groups) {
756
-			throw new OCSException('Unknown error occurred', 102);
757
-		} else {
758
-			return new DataResponse($groups);
759
-		}
760
-	}
761
-
762
-	/**
763
-	 * @param string $userId
764
-	 * @return array
765
-	 * @throws \OCP\Files\NotFoundException
766
-	 */
767
-	protected function fillStorageInfo($userId) {
768
-		try {
769
-			\OC_Util::tearDownFS();
770
-			\OC_Util::setupFS($userId);
771
-			$storage = OC_Helper::getStorageInfo('/');
772
-			$data = [
773
-				'free' => $storage['free'],
774
-				'used' => $storage['used'],
775
-				'total' => $storage['total'],
776
-				'relative' => $storage['relative'],
777
-				'quota' => $storage['quota'],
778
-			];
779
-		} catch (NotFoundException $ex) {
780
-			$data = [];
781
-		}
782
-		return $data;
783
-	}
784
-
785
-	/**
786
-	 * @NoAdminRequired
787
-	 * @PasswordConfirmationRequired
788
-	 *
789
-	 * resend welcome message
790
-	 *
791
-	 * @param string $userId
792
-	 * @return DataResponse
793
-	 * @throws OCSException
794
-	 */
795
-	public function resendWelcomeMessage($userId) {
796
-		$currentLoggedInUser = $this->userSession->getUser();
797
-
798
-		$targetUser = $this->userManager->get($userId);
799
-		if($targetUser === null) {
800
-			throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
801
-		}
802
-
803
-		// Check if admin / subadmin
804
-		$subAdminManager = $this->groupManager->getSubAdmin();
805
-		if(!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
806
-			&& !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
807
-			// No rights
808
-			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
809
-		}
810
-
811
-		$email = $targetUser->getEMailAddress();
812
-		if ($email === '' || $email === null) {
813
-			throw new OCSException('Email address not available', 101);
814
-		}
815
-		$username = $targetUser->getUID();
816
-		$lang = $this->config->getUserValue($username, 'core', 'lang', 'en');
817
-		if (!$this->l10nFactory->languageExists('settings', $lang)) {
818
-			$lang = 'en';
819
-		}
820
-
821
-		$l10n = $this->l10nFactory->get('settings', $lang);
822
-
823
-		try {
824
-			$this->newUserMailHelper->setL10N($l10n);
825
-			$emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
826
-			$this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
827
-		} catch(\Exception $e) {
828
-			$this->logger->error("Can't send new user mail to $email: " . $e->getMessage(), array('app' => 'settings'));
829
-			throw new OCSException('Sending email failed', 102);
830
-		}
831
-
832
-		return new DataResponse();
833
-	}
52
+    /** @var IUserManager */
53
+    private $userManager;
54
+    /** @var IConfig */
55
+    private $config;
56
+    /** @var IAppManager */
57
+    private $appManager;
58
+    /** @var IGroupManager|\OC\Group\Manager */ // FIXME Requires a method that is not on the interface
59
+    private $groupManager;
60
+    /** @var IUserSession */
61
+    private $userSession;
62
+    /** @var AccountManager */
63
+    private $accountManager;
64
+    /** @var ILogger */
65
+    private $logger;
66
+    /** @var IFactory */
67
+    private $l10nFactory;
68
+    /** @var NewUserMailHelper */
69
+    private $newUserMailHelper;
70
+
71
+    /**
72
+     * @param string $appName
73
+     * @param IRequest $request
74
+     * @param IUserManager $userManager
75
+     * @param IConfig $config
76
+     * @param IAppManager $appManager
77
+     * @param IGroupManager $groupManager
78
+     * @param IUserSession $userSession
79
+     * @param AccountManager $accountManager
80
+     * @param ILogger $logger
81
+     * @param IFactory $l10nFactory
82
+     * @param NewUserMailHelper $newUserMailHelper
83
+     */
84
+    public function __construct($appName,
85
+                                IRequest $request,
86
+                                IUserManager $userManager,
87
+                                IConfig $config,
88
+                                IAppManager $appManager,
89
+                                IGroupManager $groupManager,
90
+                                IUserSession $userSession,
91
+                                AccountManager $accountManager,
92
+                                ILogger $logger,
93
+                                IFactory $l10nFactory,
94
+                                NewUserMailHelper $newUserMailHelper) {
95
+        parent::__construct($appName, $request);
96
+
97
+        $this->userManager = $userManager;
98
+        $this->config = $config;
99
+        $this->appManager = $appManager;
100
+        $this->groupManager = $groupManager;
101
+        $this->userSession = $userSession;
102
+        $this->accountManager = $accountManager;
103
+        $this->logger = $logger;
104
+        $this->l10nFactory = $l10nFactory;
105
+        $this->newUserMailHelper = $newUserMailHelper;
106
+    }
107
+
108
+    /**
109
+     * @NoAdminRequired
110
+     *
111
+     * returns a list of users
112
+     *
113
+     * @param string $search
114
+     * @param int $limit
115
+     * @param int $offset
116
+     * @return DataResponse
117
+     */
118
+    public function getUsers($search = '', $limit = null, $offset = null) {
119
+        $user = $this->userSession->getUser();
120
+        $users = [];
121
+
122
+        // Admin? Or SubAdmin?
123
+        $uid = $user->getUID();
124
+        $subAdminManager = $this->groupManager->getSubAdmin();
125
+        if($this->groupManager->isAdmin($uid)){
126
+            $users = $this->userManager->search($search, $limit, $offset);
127
+        } else if ($subAdminManager->isSubAdmin($user)) {
128
+            $subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
129
+            foreach ($subAdminOfGroups as $key => $group) {
130
+                $subAdminOfGroups[$key] = $group->getGID();
131
+            }
132
+
133
+            if($offset === null) {
134
+                $offset = 0;
135
+            }
136
+
137
+            $users = [];
138
+            foreach ($subAdminOfGroups as $group) {
139
+                $users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search));
140
+            }
141
+
142
+            $users = array_slice($users, $offset, $limit);
143
+        }
144
+
145
+        $users = array_keys($users);
146
+
147
+        return new DataResponse([
148
+            'users' => $users
149
+        ]);
150
+    }
151
+
152
+    /**
153
+     * @PasswordConfirmationRequired
154
+     * @NoAdminRequired
155
+     *
156
+     * @param string $userid
157
+     * @param string $password
158
+     * @param array $groups
159
+     * @return DataResponse
160
+     * @throws OCSException
161
+     */
162
+    public function addUser($userid, $password, $groups = null) {
163
+        $user = $this->userSession->getUser();
164
+        $isAdmin = $this->groupManager->isAdmin($user->getUID());
165
+        $subAdminManager = $this->groupManager->getSubAdmin();
166
+
167
+        if($this->userManager->userExists($userid)) {
168
+            $this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
169
+            throw new OCSException('User already exists', 102);
170
+        }
171
+
172
+        if(is_array($groups)) {
173
+            foreach ($groups as $group) {
174
+                if(!$this->groupManager->groupExists($group)) {
175
+                    throw new OCSException('group '.$group.' does not exist', 104);
176
+                }
177
+                if(!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) {
178
+                    throw new OCSException('insufficient privileges for group '. $group, 105);
179
+                }
180
+            }
181
+        } else {
182
+            if(!$isAdmin) {
183
+                throw new OCSException('no group specified (required for subadmins)', 106);
184
+            }
185
+        }
186
+
187
+        try {
188
+            $newUser = $this->userManager->createUser($userid, $password);
189
+            $this->logger->info('Successful addUser call with userid: '.$userid, ['app' => 'ocs_api']);
190
+
191
+            if (is_array($groups)) {
192
+                foreach ($groups as $group) {
193
+                    $this->groupManager->get($group)->addUser($newUser);
194
+                    $this->logger->info('Added userid '.$userid.' to group '.$group, ['app' => 'ocs_api']);
195
+                }
196
+            }
197
+            return new DataResponse();
198
+        } catch (\Exception $e) {
199
+            $this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
200
+            throw new OCSException('Bad request', 101);
201
+        }
202
+    }
203
+
204
+    /**
205
+     * @NoAdminRequired
206
+     * @NoSubAdminRequired
207
+     *
208
+     * gets user info
209
+     *
210
+     * @param string $userId
211
+     * @return DataResponse
212
+     * @throws OCSException
213
+     */
214
+    public function getUser($userId) {
215
+        $data = $this->getUserData($userId);
216
+        return new DataResponse($data);
217
+    }
218
+
219
+    /**
220
+     * @NoAdminRequired
221
+     * @NoSubAdminRequired
222
+     *
223
+     * gets user info from the currently logged in user
224
+     *
225
+     * @return DataResponse
226
+     * @throws OCSException
227
+     */
228
+    public function getCurrentUser() {
229
+        $user = $this->userSession->getUser();
230
+        if ($user) {
231
+            $data =  $this->getUserData($user->getUID());
232
+            // rename "displayname" to "display-name" only for this call to keep
233
+            // the API stable.
234
+            $data['display-name'] = $data['displayname'];
235
+            unset($data['displayname']);
236
+            return new DataResponse($data);
237
+
238
+        }
239
+
240
+        throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
241
+    }
242
+
243
+    /**
244
+     * creates a array with all user data
245
+     *
246
+     * @param $userId
247
+     * @return array
248
+     * @throws OCSException
249
+     */
250
+    protected function getUserData($userId) {
251
+        $currentLoggedInUser = $this->userSession->getUser();
252
+
253
+        $data = [];
254
+
255
+        // Check if the target user exists
256
+        $targetUserObject = $this->userManager->get($userId);
257
+        if($targetUserObject === null) {
258
+            throw new OCSException('The requested user could not be found', \OCP\API::RESPOND_NOT_FOUND);
259
+        }
260
+
261
+        // Admin? Or SubAdmin?
262
+        if($this->groupManager->isAdmin($currentLoggedInUser->getUID())
263
+            || $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) {
264
+            $data['enabled'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'enabled', 'true');
265
+        } else {
266
+            // Check they are looking up themselves
267
+            if($currentLoggedInUser->getUID() !== $targetUserObject->getUID()) {
268
+                throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
269
+            }
270
+        }
271
+
272
+        $userAccount = $this->accountManager->getUser($targetUserObject);
273
+        $groups = $this->groupManager->getUserGroups($targetUserObject);
274
+        $gids = [];
275
+        foreach ($groups as $group) {
276
+            $gids[] = $group->getDisplayName();
277
+        }
278
+
279
+        // Find the data
280
+        $data['id'] = $targetUserObject->getUID();
281
+        $data['quota'] = $this->fillStorageInfo($targetUserObject->getUID());
282
+        $data[AccountManager::PROPERTY_EMAIL] = $targetUserObject->getEMailAddress();
283
+        $data[AccountManager::PROPERTY_DISPLAYNAME] = $targetUserObject->getDisplayName();
284
+        $data[AccountManager::PROPERTY_PHONE] = $userAccount[AccountManager::PROPERTY_PHONE]['value'];
285
+        $data[AccountManager::PROPERTY_ADDRESS] = $userAccount[AccountManager::PROPERTY_ADDRESS]['value'];
286
+        $data[AccountManager::PROPERTY_WEBSITE] = $userAccount[AccountManager::PROPERTY_WEBSITE]['value'];
287
+        $data[AccountManager::PROPERTY_TWITTER] = $userAccount[AccountManager::PROPERTY_TWITTER]['value'];
288
+        $data['groups'] = $gids;
289
+        $data['language'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'lang');
290
+
291
+        return $data;
292
+    }
293
+
294
+    /**
295
+     * @NoAdminRequired
296
+     * @NoSubAdminRequired
297
+     * @PasswordConfirmationRequired
298
+     *
299
+     * edit users
300
+     *
301
+     * @param string $userId
302
+     * @param string $key
303
+     * @param string $value
304
+     * @return DataResponse
305
+     * @throws OCSException
306
+     * @throws OCSForbiddenException
307
+     */
308
+    public function editUser($userId, $key, $value) {
309
+        $currentLoggedInUser = $this->userSession->getUser();
310
+
311
+        $targetUser = $this->userManager->get($userId);
312
+        if($targetUser === null) {
313
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
314
+        }
315
+
316
+        $permittedFields = [];
317
+        if($targetUser->getUID() === $currentLoggedInUser->getUID()) {
318
+            // Editing self (display, email)
319
+            if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
320
+                $permittedFields[] = 'display';
321
+                $permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
322
+                $permittedFields[] = AccountManager::PROPERTY_EMAIL;
323
+            }
324
+
325
+            $permittedFields[] = 'password';
326
+            if ($this->config->getSystemValue('force_language', false) === false ||
327
+                $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
328
+                $permittedFields[] = 'language';
329
+            }
330
+
331
+            if ($this->appManager->isEnabledForUser('federatedfilesharing')) {
332
+                $federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
333
+                $shareProvider = $federatedFileSharing->getFederatedShareProvider();
334
+                if ($shareProvider->isLookupServerUploadEnabled()) {
335
+                    $permittedFields[] = AccountManager::PROPERTY_PHONE;
336
+                    $permittedFields[] = AccountManager::PROPERTY_ADDRESS;
337
+                    $permittedFields[] = AccountManager::PROPERTY_WEBSITE;
338
+                    $permittedFields[] = AccountManager::PROPERTY_TWITTER;
339
+                }
340
+            }
341
+
342
+            // If admin they can edit their own quota
343
+            if($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
344
+                $permittedFields[] = 'quota';
345
+            }
346
+        } else {
347
+            // Check if admin / subadmin
348
+            $subAdminManager = $this->groupManager->getSubAdmin();
349
+            if($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
350
+            || $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
351
+                // They have permissions over the user
352
+                $permittedFields[] = 'display';
353
+                $permittedFields[] = AccountManager::PROPERTY_DISPLAYNAME;
354
+                $permittedFields[] = AccountManager::PROPERTY_EMAIL;
355
+                $permittedFields[] = 'password';
356
+                $permittedFields[] = 'language';
357
+                $permittedFields[] = AccountManager::PROPERTY_PHONE;
358
+                $permittedFields[] = AccountManager::PROPERTY_ADDRESS;
359
+                $permittedFields[] = AccountManager::PROPERTY_WEBSITE;
360
+                $permittedFields[] = AccountManager::PROPERTY_TWITTER;
361
+                $permittedFields[] = 'quota';
362
+            } else {
363
+                // No rights
364
+                throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
365
+            }
366
+        }
367
+        // Check if permitted to edit this field
368
+        if(!in_array($key, $permittedFields)) {
369
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
370
+        }
371
+        // Process the edit
372
+        switch($key) {
373
+            case 'display':
374
+            case AccountManager::PROPERTY_DISPLAYNAME:
375
+                $targetUser->setDisplayName($value);
376
+                break;
377
+            case 'quota':
378
+                $quota = $value;
379
+                if($quota !== 'none' && $quota !== 'default') {
380
+                    if (is_numeric($quota)) {
381
+                        $quota = (float) $quota;
382
+                    } else {
383
+                        $quota = \OCP\Util::computerFileSize($quota);
384
+                    }
385
+                    if ($quota === false) {
386
+                        throw new OCSException('Invalid quota value '.$value, 103);
387
+                    }
388
+                    if($quota === 0) {
389
+                        $quota = 'default';
390
+                    }else if($quota === -1) {
391
+                        $quota = 'none';
392
+                    } else {
393
+                        $quota = \OCP\Util::humanFileSize($quota);
394
+                    }
395
+                }
396
+                $targetUser->setQuota($quota);
397
+                break;
398
+            case 'password':
399
+                $targetUser->setPassword($value);
400
+                break;
401
+            case 'language':
402
+                $languagesCodes = $this->l10nFactory->findAvailableLanguages();
403
+                if (!in_array($value, $languagesCodes, true) && $value !== 'en') {
404
+                    throw new OCSException('Invalid language', 102);
405
+                }
406
+                $this->config->setUserValue($targetUser->getUID(), 'core', 'lang', $value);
407
+                break;
408
+            case AccountManager::PROPERTY_EMAIL:
409
+                if(filter_var($value, FILTER_VALIDATE_EMAIL)) {
410
+                    $targetUser->setEMailAddress($value);
411
+                } else {
412
+                    throw new OCSException('', 102);
413
+                }
414
+                break;
415
+            case AccountManager::PROPERTY_PHONE:
416
+            case AccountManager::PROPERTY_ADDRESS:
417
+            case AccountManager::PROPERTY_WEBSITE:
418
+            case AccountManager::PROPERTY_TWITTER:
419
+                $userAccount = $this->accountManager->getUser($targetUser);
420
+                if ($userAccount[$key]['value'] !== $value) {
421
+                    $userAccount[$key]['value'] = $value;
422
+                    $this->accountManager->updateUser($targetUser, $userAccount);
423
+                }
424
+                break;
425
+            default:
426
+                throw new OCSException('', 103);
427
+        }
428
+        return new DataResponse();
429
+    }
430
+
431
+    /**
432
+     * @PasswordConfirmationRequired
433
+     * @NoAdminRequired
434
+     *
435
+     * @param string $userId
436
+     * @return DataResponse
437
+     * @throws OCSException
438
+     * @throws OCSForbiddenException
439
+     */
440
+    public function deleteUser($userId) {
441
+        $currentLoggedInUser = $this->userSession->getUser();
442
+
443
+        $targetUser = $this->userManager->get($userId);
444
+
445
+        if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
446
+            throw new OCSException('', 101);
447
+        }
448
+
449
+        // If not permitted
450
+        $subAdminManager = $this->groupManager->getSubAdmin();
451
+        if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
452
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
453
+        }
454
+
455
+        // Go ahead with the delete
456
+        if($targetUser->delete()) {
457
+            return new DataResponse();
458
+        } else {
459
+            throw new OCSException('', 101);
460
+        }
461
+    }
462
+
463
+    /**
464
+     * @PasswordConfirmationRequired
465
+     * @NoAdminRequired
466
+     *
467
+     * @param string $userId
468
+     * @return DataResponse
469
+     * @throws OCSException
470
+     * @throws OCSForbiddenException
471
+     */
472
+    public function disableUser($userId) {
473
+        return $this->setEnabled($userId, false);
474
+    }
475
+
476
+    /**
477
+     * @PasswordConfirmationRequired
478
+     * @NoAdminRequired
479
+     *
480
+     * @param string $userId
481
+     * @return DataResponse
482
+     * @throws OCSException
483
+     * @throws OCSForbiddenException
484
+     */
485
+    public function enableUser($userId) {
486
+        return $this->setEnabled($userId, true);
487
+    }
488
+
489
+    /**
490
+     * @param string $userId
491
+     * @param bool $value
492
+     * @return DataResponse
493
+     * @throws OCSException
494
+     * @throws OCSForbiddenException
495
+     */
496
+    private function setEnabled($userId, $value) {
497
+        $currentLoggedInUser = $this->userSession->getUser();
498
+
499
+        $targetUser = $this->userManager->get($userId);
500
+        if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
501
+            throw new OCSException('', 101);
502
+        }
503
+
504
+        // If not permitted
505
+        $subAdminManager = $this->groupManager->getSubAdmin();
506
+        if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
507
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
508
+        }
509
+
510
+        // enable/disable the user now
511
+        $targetUser->setEnabled($value);
512
+        return new DataResponse();
513
+    }
514
+
515
+    /**
516
+     * @NoAdminRequired
517
+     * @NoSubAdminRequired
518
+     *
519
+     * @param string $userId
520
+     * @return DataResponse
521
+     * @throws OCSException
522
+     */
523
+    public function getUsersGroups($userId) {
524
+        $loggedInUser = $this->userSession->getUser();
525
+
526
+        $targetUser = $this->userManager->get($userId);
527
+        if($targetUser === null) {
528
+            throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
529
+        }
530
+
531
+        if($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
532
+            // Self lookup or admin lookup
533
+            return new DataResponse([
534
+                'groups' => $this->groupManager->getUserGroupIds($targetUser)
535
+            ]);
536
+        } else {
537
+            $subAdminManager = $this->groupManager->getSubAdmin();
538
+
539
+            // Looking up someone else
540
+            if($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
541
+                // Return the group that the method caller is subadmin of for the user in question
542
+                /** @var IGroup[] $getSubAdminsGroups */
543
+                $getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
544
+                foreach ($getSubAdminsGroups as $key => $group) {
545
+                    $getSubAdminsGroups[$key] = $group->getGID();
546
+                }
547
+                $groups = array_intersect(
548
+                    $getSubAdminsGroups,
549
+                    $this->groupManager->getUserGroupIds($targetUser)
550
+                );
551
+                return new DataResponse(['groups' => $groups]);
552
+            } else {
553
+                // Not permitted
554
+                throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
555
+            }
556
+        }
557
+
558
+    }
559
+
560
+    /**
561
+     * @PasswordConfirmationRequired
562
+     * @NoAdminRequired
563
+     *
564
+     * @param string $userId
565
+     * @param string $groupid
566
+     * @return DataResponse
567
+     * @throws OCSException
568
+     */
569
+    public function addToGroup($userId, $groupid = '') {
570
+        if($groupid === '') {
571
+            throw new OCSException('', 101);
572
+        }
573
+
574
+        $group = $this->groupManager->get($groupid);
575
+        $targetUser = $this->userManager->get($userId);
576
+        if($group === null) {
577
+            throw new OCSException('', 102);
578
+        }
579
+        if($targetUser === null) {
580
+            throw new OCSException('', 103);
581
+        }
582
+
583
+        // If they're not an admin, check they are a subadmin of the group in question
584
+        $loggedInUser = $this->userSession->getUser();
585
+        $subAdminManager = $this->groupManager->getSubAdmin();
586
+        if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
587
+            throw new OCSException('', 104);
588
+        }
589
+
590
+        // Add user to group
591
+        $group->addUser($targetUser);
592
+        return new DataResponse();
593
+    }
594
+
595
+    /**
596
+     * @PasswordConfirmationRequired
597
+     * @NoAdminRequired
598
+     *
599
+     * @param string $userId
600
+     * @param string $groupid
601
+     * @return DataResponse
602
+     * @throws OCSException
603
+     */
604
+    public function removeFromGroup($userId, $groupid) {
605
+        $loggedInUser = $this->userSession->getUser();
606
+
607
+        if($groupid === null || trim($groupid) === '') {
608
+            throw new OCSException('', 101);
609
+        }
610
+
611
+        $group = $this->groupManager->get($groupid);
612
+        if($group === null) {
613
+            throw new OCSException('', 102);
614
+        }
615
+
616
+        $targetUser = $this->userManager->get($userId);
617
+        if($targetUser === null) {
618
+            throw new OCSException('', 103);
619
+        }
620
+
621
+        // If they're not an admin, check they are a subadmin of the group in question
622
+        $subAdminManager = $this->groupManager->getSubAdmin();
623
+        if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
624
+            throw new OCSException('', 104);
625
+        }
626
+
627
+        // Check they aren't removing themselves from 'admin' or their 'subadmin; group
628
+        if ($targetUser->getUID() === $loggedInUser->getUID()) {
629
+            if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
630
+                if ($group->getGID() === 'admin') {
631
+                    throw new OCSException('Cannot remove yourself from the admin group', 105);
632
+                }
633
+            } else {
634
+                // Not an admin, so the user must be a subadmin of this group, but that is not allowed.
635
+                throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
636
+            }
637
+
638
+        } else if (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
639
+            /** @var IGroup[] $subAdminGroups */
640
+            $subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
641
+            $subAdminGroups = array_map(function (IGroup $subAdminGroup) {
642
+                return $subAdminGroup->getGID();
643
+            }, $subAdminGroups);
644
+            $userGroups = $this->groupManager->getUserGroupIds($targetUser);
645
+            $userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
646
+
647
+            if (count($userSubAdminGroups) <= 1) {
648
+                // Subadmin must not be able to remove a user from all their subadmin groups.
649
+                throw new OCSException('Cannot remove user from this group as this is the only remaining group you are a SubAdmin of', 105);
650
+            }
651
+        }
652
+
653
+        // Remove user from group
654
+        $group->removeUser($targetUser);
655
+        return new DataResponse();
656
+    }
657
+
658
+    /**
659
+     * Creates a subadmin
660
+     *
661
+     * @PasswordConfirmationRequired
662
+     *
663
+     * @param string $userId
664
+     * @param string $groupid
665
+     * @return DataResponse
666
+     * @throws OCSException
667
+     */
668
+    public function addSubAdmin($userId, $groupid) {
669
+        $group = $this->groupManager->get($groupid);
670
+        $user = $this->userManager->get($userId);
671
+
672
+        // Check if the user exists
673
+        if($user === null) {
674
+            throw new OCSException('User does not exist', 101);
675
+        }
676
+        // Check if group exists
677
+        if($group === null) {
678
+            throw new OCSException('Group does not exist',  102);
679
+        }
680
+        // Check if trying to make subadmin of admin group
681
+        if($group->getGID() === 'admin') {
682
+            throw new OCSException('Cannot create subadmins for admin group', 103);
683
+        }
684
+
685
+        $subAdminManager = $this->groupManager->getSubAdmin();
686
+
687
+        // We cannot be subadmin twice
688
+        if ($subAdminManager->isSubAdminofGroup($user, $group)) {
689
+            return new DataResponse();
690
+        }
691
+        // Go
692
+        if($subAdminManager->createSubAdmin($user, $group)) {
693
+            return new DataResponse();
694
+        } else {
695
+            throw new OCSException('Unknown error occurred', 103);
696
+        }
697
+    }
698
+
699
+    /**
700
+     * Removes a subadmin from a group
701
+     *
702
+     * @PasswordConfirmationRequired
703
+     *
704
+     * @param string $userId
705
+     * @param string $groupid
706
+     * @return DataResponse
707
+     * @throws OCSException
708
+     */
709
+    public function removeSubAdmin($userId, $groupid) {
710
+        $group = $this->groupManager->get($groupid);
711
+        $user = $this->userManager->get($userId);
712
+        $subAdminManager = $this->groupManager->getSubAdmin();
713
+
714
+        // Check if the user exists
715
+        if($user === null) {
716
+            throw new OCSException('User does not exist', 101);
717
+        }
718
+        // Check if the group exists
719
+        if($group === null) {
720
+            throw new OCSException('Group does not exist', 101);
721
+        }
722
+        // Check if they are a subadmin of this said group
723
+        if(!$subAdminManager->isSubAdminOfGroup($user, $group)) {
724
+            throw new OCSException('User is not a subadmin of this group', 102);
725
+        }
726
+
727
+        // Go
728
+        if($subAdminManager->deleteSubAdmin($user, $group)) {
729
+            return new DataResponse();
730
+        } else {
731
+            throw new OCSException('Unknown error occurred', 103);
732
+        }
733
+    }
734
+
735
+    /**
736
+     * Get the groups a user is a subadmin of
737
+     *
738
+     * @param string $userId
739
+     * @return DataResponse
740
+     * @throws OCSException
741
+     */
742
+    public function getUserSubAdminGroups($userId) {
743
+        $user = $this->userManager->get($userId);
744
+        // Check if the user exists
745
+        if($user === null) {
746
+            throw new OCSException('User does not exist', 101);
747
+        }
748
+
749
+        // Get the subadmin groups
750
+        $groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user);
751
+        foreach ($groups as $key => $group) {
752
+            $groups[$key] = $group->getGID();
753
+        }
754
+
755
+        if(!$groups) {
756
+            throw new OCSException('Unknown error occurred', 102);
757
+        } else {
758
+            return new DataResponse($groups);
759
+        }
760
+    }
761
+
762
+    /**
763
+     * @param string $userId
764
+     * @return array
765
+     * @throws \OCP\Files\NotFoundException
766
+     */
767
+    protected function fillStorageInfo($userId) {
768
+        try {
769
+            \OC_Util::tearDownFS();
770
+            \OC_Util::setupFS($userId);
771
+            $storage = OC_Helper::getStorageInfo('/');
772
+            $data = [
773
+                'free' => $storage['free'],
774
+                'used' => $storage['used'],
775
+                'total' => $storage['total'],
776
+                'relative' => $storage['relative'],
777
+                'quota' => $storage['quota'],
778
+            ];
779
+        } catch (NotFoundException $ex) {
780
+            $data = [];
781
+        }
782
+        return $data;
783
+    }
784
+
785
+    /**
786
+     * @NoAdminRequired
787
+     * @PasswordConfirmationRequired
788
+     *
789
+     * resend welcome message
790
+     *
791
+     * @param string $userId
792
+     * @return DataResponse
793
+     * @throws OCSException
794
+     */
795
+    public function resendWelcomeMessage($userId) {
796
+        $currentLoggedInUser = $this->userSession->getUser();
797
+
798
+        $targetUser = $this->userManager->get($userId);
799
+        if($targetUser === null) {
800
+            throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
801
+        }
802
+
803
+        // Check if admin / subadmin
804
+        $subAdminManager = $this->groupManager->getSubAdmin();
805
+        if(!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
806
+            && !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
807
+            // No rights
808
+            throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
809
+        }
810
+
811
+        $email = $targetUser->getEMailAddress();
812
+        if ($email === '' || $email === null) {
813
+            throw new OCSException('Email address not available', 101);
814
+        }
815
+        $username = $targetUser->getUID();
816
+        $lang = $this->config->getUserValue($username, 'core', 'lang', 'en');
817
+        if (!$this->l10nFactory->languageExists('settings', $lang)) {
818
+            $lang = 'en';
819
+        }
820
+
821
+        $l10n = $this->l10nFactory->get('settings', $lang);
822
+
823
+        try {
824
+            $this->newUserMailHelper->setL10N($l10n);
825
+            $emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
826
+            $this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
827
+        } catch(\Exception $e) {
828
+            $this->logger->error("Can't send new user mail to $email: " . $e->getMessage(), array('app' => 'settings'));
829
+            throw new OCSException('Sending email failed', 102);
830
+        }
831
+
832
+        return new DataResponse();
833
+    }
834 834
 }
Please login to merge, or discard this patch.
Spacing   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -122,7 +122,7 @@  discard block
 block discarded – undo
122 122
 		// Admin? Or SubAdmin?
123 123
 		$uid = $user->getUID();
124 124
 		$subAdminManager = $this->groupManager->getSubAdmin();
125
-		if($this->groupManager->isAdmin($uid)){
125
+		if ($this->groupManager->isAdmin($uid)) {
126 126
 			$users = $this->userManager->search($search, $limit, $offset);
127 127
 		} else if ($subAdminManager->isSubAdmin($user)) {
128 128
 			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
@@ -130,7 +130,7 @@  discard block
 block discarded – undo
130 130
 				$subAdminOfGroups[$key] = $group->getGID();
131 131
 			}
132 132
 
133
-			if($offset === null) {
133
+			if ($offset === null) {
134 134
 				$offset = 0;
135 135
 			}
136 136
 
@@ -164,22 +164,22 @@  discard block
 block discarded – undo
164 164
 		$isAdmin = $this->groupManager->isAdmin($user->getUID());
165 165
 		$subAdminManager = $this->groupManager->getSubAdmin();
166 166
 
167
-		if($this->userManager->userExists($userid)) {
167
+		if ($this->userManager->userExists($userid)) {
168 168
 			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
169 169
 			throw new OCSException('User already exists', 102);
170 170
 		}
171 171
 
172
-		if(is_array($groups)) {
172
+		if (is_array($groups)) {
173 173
 			foreach ($groups as $group) {
174
-				if(!$this->groupManager->groupExists($group)) {
174
+				if (!$this->groupManager->groupExists($group)) {
175 175
 					throw new OCSException('group '.$group.' does not exist', 104);
176 176
 				}
177
-				if(!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) {
178
-					throw new OCSException('insufficient privileges for group '. $group, 105);
177
+				if (!$isAdmin && !$subAdminManager->isSubAdminofGroup($user, $this->groupManager->get($group))) {
178
+					throw new OCSException('insufficient privileges for group '.$group, 105);
179 179
 				}
180 180
 			}
181 181
 		} else {
182
-			if(!$isAdmin) {
182
+			if (!$isAdmin) {
183 183
 				throw new OCSException('no group specified (required for subadmins)', 106);
184 184
 			}
185 185
 		}
@@ -228,7 +228,7 @@  discard block
 block discarded – undo
228 228
 	public function getCurrentUser() {
229 229
 		$user = $this->userSession->getUser();
230 230
 		if ($user) {
231
-			$data =  $this->getUserData($user->getUID());
231
+			$data = $this->getUserData($user->getUID());
232 232
 			// rename "displayname" to "display-name" only for this call to keep
233 233
 			// the API stable.
234 234
 			$data['display-name'] = $data['displayname'];
@@ -254,17 +254,17 @@  discard block
 block discarded – undo
254 254
 
255 255
 		// Check if the target user exists
256 256
 		$targetUserObject = $this->userManager->get($userId);
257
-		if($targetUserObject === null) {
257
+		if ($targetUserObject === null) {
258 258
 			throw new OCSException('The requested user could not be found', \OCP\API::RESPOND_NOT_FOUND);
259 259
 		}
260 260
 
261 261
 		// Admin? Or SubAdmin?
262
-		if($this->groupManager->isAdmin($currentLoggedInUser->getUID())
262
+		if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())
263 263
 			|| $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) {
264 264
 			$data['enabled'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'enabled', 'true');
265 265
 		} else {
266 266
 			// Check they are looking up themselves
267
-			if($currentLoggedInUser->getUID() !== $targetUserObject->getUID()) {
267
+			if ($currentLoggedInUser->getUID() !== $targetUserObject->getUID()) {
268 268
 				throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
269 269
 			}
270 270
 		}
@@ -309,12 +309,12 @@  discard block
 block discarded – undo
309 309
 		$currentLoggedInUser = $this->userSession->getUser();
310 310
 
311 311
 		$targetUser = $this->userManager->get($userId);
312
-		if($targetUser === null) {
312
+		if ($targetUser === null) {
313 313
 			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
314 314
 		}
315 315
 
316 316
 		$permittedFields = [];
317
-		if($targetUser->getUID() === $currentLoggedInUser->getUID()) {
317
+		if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
318 318
 			// Editing self (display, email)
319 319
 			if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
320 320
 				$permittedFields[] = 'display';
@@ -340,13 +340,13 @@  discard block
 block discarded – undo
340 340
 			}
341 341
 
342 342
 			// If admin they can edit their own quota
343
-			if($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
343
+			if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
344 344
 				$permittedFields[] = 'quota';
345 345
 			}
346 346
 		} else {
347 347
 			// Check if admin / subadmin
348 348
 			$subAdminManager = $this->groupManager->getSubAdmin();
349
-			if($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
349
+			if ($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
350 350
 			|| $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
351 351
 				// They have permissions over the user
352 352
 				$permittedFields[] = 'display';
@@ -365,18 +365,18 @@  discard block
 block discarded – undo
365 365
 			}
366 366
 		}
367 367
 		// Check if permitted to edit this field
368
-		if(!in_array($key, $permittedFields)) {
368
+		if (!in_array($key, $permittedFields)) {
369 369
 			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
370 370
 		}
371 371
 		// Process the edit
372
-		switch($key) {
372
+		switch ($key) {
373 373
 			case 'display':
374 374
 			case AccountManager::PROPERTY_DISPLAYNAME:
375 375
 				$targetUser->setDisplayName($value);
376 376
 				break;
377 377
 			case 'quota':
378 378
 				$quota = $value;
379
-				if($quota !== 'none' && $quota !== 'default') {
379
+				if ($quota !== 'none' && $quota !== 'default') {
380 380
 					if (is_numeric($quota)) {
381 381
 						$quota = (float) $quota;
382 382
 					} else {
@@ -385,9 +385,9 @@  discard block
 block discarded – undo
385 385
 					if ($quota === false) {
386 386
 						throw new OCSException('Invalid quota value '.$value, 103);
387 387
 					}
388
-					if($quota === 0) {
388
+					if ($quota === 0) {
389 389
 						$quota = 'default';
390
-					}else if($quota === -1) {
390
+					} else if ($quota === -1) {
391 391
 						$quota = 'none';
392 392
 					} else {
393 393
 						$quota = \OCP\Util::humanFileSize($quota);
@@ -406,7 +406,7 @@  discard block
 block discarded – undo
406 406
 				$this->config->setUserValue($targetUser->getUID(), 'core', 'lang', $value);
407 407
 				break;
408 408
 			case AccountManager::PROPERTY_EMAIL:
409
-				if(filter_var($value, FILTER_VALIDATE_EMAIL)) {
409
+				if (filter_var($value, FILTER_VALIDATE_EMAIL)) {
410 410
 					$targetUser->setEMailAddress($value);
411 411
 				} else {
412 412
 					throw new OCSException('', 102);
@@ -442,18 +442,18 @@  discard block
 block discarded – undo
442 442
 
443 443
 		$targetUser = $this->userManager->get($userId);
444 444
 
445
-		if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
445
+		if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
446 446
 			throw new OCSException('', 101);
447 447
 		}
448 448
 
449 449
 		// If not permitted
450 450
 		$subAdminManager = $this->groupManager->getSubAdmin();
451
-		if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
451
+		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
452 452
 			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
453 453
 		}
454 454
 
455 455
 		// Go ahead with the delete
456
-		if($targetUser->delete()) {
456
+		if ($targetUser->delete()) {
457 457
 			return new DataResponse();
458 458
 		} else {
459 459
 			throw new OCSException('', 101);
@@ -497,13 +497,13 @@  discard block
 block discarded – undo
497 497
 		$currentLoggedInUser = $this->userSession->getUser();
498 498
 
499 499
 		$targetUser = $this->userManager->get($userId);
500
-		if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
500
+		if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
501 501
 			throw new OCSException('', 101);
502 502
 		}
503 503
 
504 504
 		// If not permitted
505 505
 		$subAdminManager = $this->groupManager->getSubAdmin();
506
-		if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
506
+		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
507 507
 			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
508 508
 		}
509 509
 
@@ -524,11 +524,11 @@  discard block
 block discarded – undo
524 524
 		$loggedInUser = $this->userSession->getUser();
525 525
 
526 526
 		$targetUser = $this->userManager->get($userId);
527
-		if($targetUser === null) {
527
+		if ($targetUser === null) {
528 528
 			throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
529 529
 		}
530 530
 
531
-		if($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
531
+		if ($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
532 532
 			// Self lookup or admin lookup
533 533
 			return new DataResponse([
534 534
 				'groups' => $this->groupManager->getUserGroupIds($targetUser)
@@ -537,7 +537,7 @@  discard block
 block discarded – undo
537 537
 			$subAdminManager = $this->groupManager->getSubAdmin();
538 538
 
539 539
 			// Looking up someone else
540
-			if($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
540
+			if ($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
541 541
 				// Return the group that the method caller is subadmin of for the user in question
542 542
 				/** @var IGroup[] $getSubAdminsGroups */
543 543
 				$getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
@@ -567,16 +567,16 @@  discard block
 block discarded – undo
567 567
 	 * @throws OCSException
568 568
 	 */
569 569
 	public function addToGroup($userId, $groupid = '') {
570
-		if($groupid === '') {
570
+		if ($groupid === '') {
571 571
 			throw new OCSException('', 101);
572 572
 		}
573 573
 
574 574
 		$group = $this->groupManager->get($groupid);
575 575
 		$targetUser = $this->userManager->get($userId);
576
-		if($group === null) {
576
+		if ($group === null) {
577 577
 			throw new OCSException('', 102);
578 578
 		}
579
-		if($targetUser === null) {
579
+		if ($targetUser === null) {
580 580
 			throw new OCSException('', 103);
581 581
 		}
582 582
 
@@ -604,17 +604,17 @@  discard block
 block discarded – undo
604 604
 	public function removeFromGroup($userId, $groupid) {
605 605
 		$loggedInUser = $this->userSession->getUser();
606 606
 
607
-		if($groupid === null || trim($groupid) === '') {
607
+		if ($groupid === null || trim($groupid) === '') {
608 608
 			throw new OCSException('', 101);
609 609
 		}
610 610
 
611 611
 		$group = $this->groupManager->get($groupid);
612
-		if($group === null) {
612
+		if ($group === null) {
613 613
 			throw new OCSException('', 102);
614 614
 		}
615 615
 
616 616
 		$targetUser = $this->userManager->get($userId);
617
-		if($targetUser === null) {
617
+		if ($targetUser === null) {
618 618
 			throw new OCSException('', 103);
619 619
 		}
620 620
 
@@ -638,7 +638,7 @@  discard block
 block discarded – undo
638 638
 		} else if (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
639 639
 			/** @var IGroup[] $subAdminGroups */
640 640
 			$subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
641
-			$subAdminGroups = array_map(function (IGroup $subAdminGroup) {
641
+			$subAdminGroups = array_map(function(IGroup $subAdminGroup) {
642 642
 				return $subAdminGroup->getGID();
643 643
 			}, $subAdminGroups);
644 644
 			$userGroups = $this->groupManager->getUserGroupIds($targetUser);
@@ -670,15 +670,15 @@  discard block
 block discarded – undo
670 670
 		$user = $this->userManager->get($userId);
671 671
 
672 672
 		// Check if the user exists
673
-		if($user === null) {
673
+		if ($user === null) {
674 674
 			throw new OCSException('User does not exist', 101);
675 675
 		}
676 676
 		// Check if group exists
677
-		if($group === null) {
678
-			throw new OCSException('Group does not exist',  102);
677
+		if ($group === null) {
678
+			throw new OCSException('Group does not exist', 102);
679 679
 		}
680 680
 		// Check if trying to make subadmin of admin group
681
-		if($group->getGID() === 'admin') {
681
+		if ($group->getGID() === 'admin') {
682 682
 			throw new OCSException('Cannot create subadmins for admin group', 103);
683 683
 		}
684 684
 
@@ -689,7 +689,7 @@  discard block
 block discarded – undo
689 689
 			return new DataResponse();
690 690
 		}
691 691
 		// Go
692
-		if($subAdminManager->createSubAdmin($user, $group)) {
692
+		if ($subAdminManager->createSubAdmin($user, $group)) {
693 693
 			return new DataResponse();
694 694
 		} else {
695 695
 			throw new OCSException('Unknown error occurred', 103);
@@ -712,20 +712,20 @@  discard block
 block discarded – undo
712 712
 		$subAdminManager = $this->groupManager->getSubAdmin();
713 713
 
714 714
 		// Check if the user exists
715
-		if($user === null) {
715
+		if ($user === null) {
716 716
 			throw new OCSException('User does not exist', 101);
717 717
 		}
718 718
 		// Check if the group exists
719
-		if($group === null) {
719
+		if ($group === null) {
720 720
 			throw new OCSException('Group does not exist', 101);
721 721
 		}
722 722
 		// Check if they are a subadmin of this said group
723
-		if(!$subAdminManager->isSubAdminOfGroup($user, $group)) {
723
+		if (!$subAdminManager->isSubAdminOfGroup($user, $group)) {
724 724
 			throw new OCSException('User is not a subadmin of this group', 102);
725 725
 		}
726 726
 
727 727
 		// Go
728
-		if($subAdminManager->deleteSubAdmin($user, $group)) {
728
+		if ($subAdminManager->deleteSubAdmin($user, $group)) {
729 729
 			return new DataResponse();
730 730
 		} else {
731 731
 			throw new OCSException('Unknown error occurred', 103);
@@ -742,7 +742,7 @@  discard block
 block discarded – undo
742 742
 	public function getUserSubAdminGroups($userId) {
743 743
 		$user = $this->userManager->get($userId);
744 744
 		// Check if the user exists
745
-		if($user === null) {
745
+		if ($user === null) {
746 746
 			throw new OCSException('User does not exist', 101);
747 747
 		}
748 748
 
@@ -752,7 +752,7 @@  discard block
 block discarded – undo
752 752
 			$groups[$key] = $group->getGID();
753 753
 		}
754 754
 
755
-		if(!$groups) {
755
+		if (!$groups) {
756 756
 			throw new OCSException('Unknown error occurred', 102);
757 757
 		} else {
758 758
 			return new DataResponse($groups);
@@ -796,13 +796,13 @@  discard block
 block discarded – undo
796 796
 		$currentLoggedInUser = $this->userSession->getUser();
797 797
 
798 798
 		$targetUser = $this->userManager->get($userId);
799
-		if($targetUser === null) {
799
+		if ($targetUser === null) {
800 800
 			throw new OCSException('', \OCP\API::RESPOND_NOT_FOUND);
801 801
 		}
802 802
 
803 803
 		// Check if admin / subadmin
804 804
 		$subAdminManager = $this->groupManager->getSubAdmin();
805
-		if(!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
805
+		if (!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
806 806
 			&& !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
807 807
 			// No rights
808 808
 			throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
@@ -824,8 +824,8 @@  discard block
 block discarded – undo
824 824
 			$this->newUserMailHelper->setL10N($l10n);
825 825
 			$emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
826 826
 			$this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
827
-		} catch(\Exception $e) {
828
-			$this->logger->error("Can't send new user mail to $email: " . $e->getMessage(), array('app' => 'settings'));
827
+		} catch (\Exception $e) {
828
+			$this->logger->error("Can't send new user mail to $email: ".$e->getMessage(), array('app' => 'settings'));
829 829
 			throw new OCSException('Sending email failed', 102);
830 830
 		}
831 831
 
Please login to merge, or discard this patch.