Passed
Push — master ( 62403d...0c3e2f )
by Joas
14:50 queued 14s
created
lib/private/Encryption/File.php 1 patch
Indentation   +90 added lines, -90 removed lines patch added patch discarded remove patch
@@ -33,95 +33,95 @@
 block discarded – undo
33 33
 
34 34
 class File implements \OCP\Encryption\IFile {
35 35
 
36
-	/** @var Util */
37
-	protected $util;
38
-
39
-	/** @var IRootFolder */
40
-	private $rootFolder;
41
-
42
-	/** @var IManager */
43
-	private $shareManager;
44
-
45
-	/**
46
-	 * cache results of already checked folders
47
-	 *
48
-	 * @var array
49
-	 */
50
-	protected $cache;
51
-
52
-	public function __construct(Util $util,
53
-								IRootFolder $rootFolder,
54
-								IManager $shareManager) {
55
-		$this->util = $util;
56
-		$this->cache = new CappedMemoryCache();
57
-		$this->rootFolder = $rootFolder;
58
-		$this->shareManager = $shareManager;
59
-	}
60
-
61
-
62
-	/**
63
-	 * get list of users with access to the file
64
-	 *
65
-	 * @param string $path to the file
66
-	 * @return array  ['users' => $uniqueUserIds, 'public' => $public]
67
-	 */
68
-	public function getAccessList($path) {
69
-
70
-		// Make sure that a share key is generated for the owner too
71
-		list($owner, $ownerPath) = $this->util->getUidAndFilename($path);
72
-
73
-		// always add owner to the list of users with access to the file
74
-		$userIds = [$owner];
75
-
76
-		if (!$this->util->isFile($owner . '/' . $ownerPath)) {
77
-			return ['users' => $userIds, 'public' => false];
78
-		}
79
-
80
-		$ownerPath = substr($ownerPath, strlen('/files'));
81
-		$userFolder = $this->rootFolder->getUserFolder($owner);
82
-		try {
83
-			$file = $userFolder->get($ownerPath);
84
-		} catch (NotFoundException $e) {
85
-			$file = null;
86
-		}
87
-		$ownerPath = $this->util->stripPartialFileExtension($ownerPath);
88
-
89
-		// first get the shares for the parent and cache the result so that we don't
90
-		// need to check all parents for every file
91
-		$parent = dirname($ownerPath);
92
-		$parentNode = $userFolder->get($parent);
93
-		if (isset($this->cache[$parent])) {
94
-			$resultForParents = $this->cache[$parent];
95
-		} else {
96
-			$resultForParents = $this->shareManager->getAccessList($parentNode);
97
-			$this->cache[$parent] = $resultForParents;
98
-		}
99
-		$userIds = array_merge($userIds, $resultForParents['users']);
100
-		$public = $resultForParents['public'] || $resultForParents['remote'];
101
-
102
-
103
-		// Find out who, if anyone, is sharing the file
104
-		if ($file !== null) {
105
-			$resultForFile = $this->shareManager->getAccessList($file, false);
106
-			$userIds = array_merge($userIds, $resultForFile['users']);
107
-			$public = $resultForFile['public'] || $resultForFile['remote'] || $public;
108
-		}
109
-
110
-		// check if it is a group mount
111
-		if (\OCP\App::isEnabled("files_external")) {
112
-			$mounts = \OC_Mount_Config::getSystemMountPoints();
113
-			foreach ($mounts as $mount) {
114
-				if ($mount['mountpoint'] == substr($ownerPath, 1, strlen($mount['mountpoint']))) {
115
-					$mountedFor = $this->util->getUserWithAccessToMountPoint($mount['applicable']['users'], $mount['applicable']['groups']);
116
-					$userIds = array_merge($userIds, $mountedFor);
117
-				}
118
-			}
119
-		}
120
-
121
-		// Remove duplicate UIDs
122
-		$uniqueUserIds = array_unique($userIds);
123
-
124
-		return ['users' => $uniqueUserIds, 'public' => $public];
125
-	}
36
+    /** @var Util */
37
+    protected $util;
38
+
39
+    /** @var IRootFolder */
40
+    private $rootFolder;
41
+
42
+    /** @var IManager */
43
+    private $shareManager;
44
+
45
+    /**
46
+     * cache results of already checked folders
47
+     *
48
+     * @var array
49
+     */
50
+    protected $cache;
51
+
52
+    public function __construct(Util $util,
53
+                                IRootFolder $rootFolder,
54
+                                IManager $shareManager) {
55
+        $this->util = $util;
56
+        $this->cache = new CappedMemoryCache();
57
+        $this->rootFolder = $rootFolder;
58
+        $this->shareManager = $shareManager;
59
+    }
60
+
61
+
62
+    /**
63
+     * get list of users with access to the file
64
+     *
65
+     * @param string $path to the file
66
+     * @return array  ['users' => $uniqueUserIds, 'public' => $public]
67
+     */
68
+    public function getAccessList($path) {
69
+
70
+        // Make sure that a share key is generated for the owner too
71
+        list($owner, $ownerPath) = $this->util->getUidAndFilename($path);
72
+
73
+        // always add owner to the list of users with access to the file
74
+        $userIds = [$owner];
75
+
76
+        if (!$this->util->isFile($owner . '/' . $ownerPath)) {
77
+            return ['users' => $userIds, 'public' => false];
78
+        }
79
+
80
+        $ownerPath = substr($ownerPath, strlen('/files'));
81
+        $userFolder = $this->rootFolder->getUserFolder($owner);
82
+        try {
83
+            $file = $userFolder->get($ownerPath);
84
+        } catch (NotFoundException $e) {
85
+            $file = null;
86
+        }
87
+        $ownerPath = $this->util->stripPartialFileExtension($ownerPath);
88
+
89
+        // first get the shares for the parent and cache the result so that we don't
90
+        // need to check all parents for every file
91
+        $parent = dirname($ownerPath);
92
+        $parentNode = $userFolder->get($parent);
93
+        if (isset($this->cache[$parent])) {
94
+            $resultForParents = $this->cache[$parent];
95
+        } else {
96
+            $resultForParents = $this->shareManager->getAccessList($parentNode);
97
+            $this->cache[$parent] = $resultForParents;
98
+        }
99
+        $userIds = array_merge($userIds, $resultForParents['users']);
100
+        $public = $resultForParents['public'] || $resultForParents['remote'];
101
+
102
+
103
+        // Find out who, if anyone, is sharing the file
104
+        if ($file !== null) {
105
+            $resultForFile = $this->shareManager->getAccessList($file, false);
106
+            $userIds = array_merge($userIds, $resultForFile['users']);
107
+            $public = $resultForFile['public'] || $resultForFile['remote'] || $public;
108
+        }
109
+
110
+        // check if it is a group mount
111
+        if (\OCP\App::isEnabled("files_external")) {
112
+            $mounts = \OC_Mount_Config::getSystemMountPoints();
113
+            foreach ($mounts as $mount) {
114
+                if ($mount['mountpoint'] == substr($ownerPath, 1, strlen($mount['mountpoint']))) {
115
+                    $mountedFor = $this->util->getUserWithAccessToMountPoint($mount['applicable']['users'], $mount['applicable']['groups']);
116
+                    $userIds = array_merge($userIds, $mountedFor);
117
+                }
118
+            }
119
+        }
120
+
121
+        // Remove duplicate UIDs
122
+        $uniqueUserIds = array_unique($userIds);
123
+
124
+        return ['users' => $uniqueUserIds, 'public' => $public];
125
+    }
126 126
 
127 127
 }
Please login to merge, or discard this patch.
lib/private/Encryption/Update.php 1 patch
Indentation   +157 added lines, -157 removed lines patch added patch discarded remove patch
@@ -34,162 +34,162 @@
 block discarded – undo
34 34
  */
35 35
 class Update {
36 36
 
37
-	/** @var \OC\Files\View */
38
-	protected $view;
39
-
40
-	/** @var \OC\Encryption\Util */
41
-	protected $util;
42
-
43
-	 /** @var \OC\Files\Mount\Manager */
44
-	protected $mountManager;
45
-
46
-	/** @var \OC\Encryption\Manager */
47
-	protected $encryptionManager;
48
-
49
-	/** @var string */
50
-	protected $uid;
51
-
52
-	/** @var \OC\Encryption\File */
53
-	protected $file;
54
-
55
-	/**
56
-	 *
57
-	 * @param \OC\Files\View $view
58
-	 * @param \OC\Encryption\Util $util
59
-	 * @param \OC\Files\Mount\Manager $mountManager
60
-	 * @param \OC\Encryption\Manager $encryptionManager
61
-	 * @param \OC\Encryption\File $file
62
-	 * @param string $uid
63
-	 */
64
-	public function __construct(
65
-			View $view,
66
-			Util $util,
67
-			Mount\Manager $mountManager,
68
-			Manager $encryptionManager,
69
-			File $file,
70
-			$uid
71
-		) {
72
-
73
-		$this->view = $view;
74
-		$this->util = $util;
75
-		$this->mountManager = $mountManager;
76
-		$this->encryptionManager = $encryptionManager;
77
-		$this->file = $file;
78
-		$this->uid = $uid;
79
-	}
80
-
81
-	/**
82
-	 * hook after file was shared
83
-	 *
84
-	 * @param array $params
85
-	 */
86
-	public function postShared($params) {
87
-		if ($this->encryptionManager->isEnabled()) {
88
-			if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
89
-				$path = Filesystem::getPath($params['fileSource']);
90
-				list($owner, $ownerPath) = $this->getOwnerPath($path);
91
-				$absPath = '/' . $owner . '/files/' . $ownerPath;
92
-				$this->update($absPath);
93
-			}
94
-		}
95
-	}
96
-
97
-	/**
98
-	 * hook after file was unshared
99
-	 *
100
-	 * @param array $params
101
-	 */
102
-	public function postUnshared($params) {
103
-		if ($this->encryptionManager->isEnabled()) {
104
-			if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
105
-				$path = Filesystem::getPath($params['fileSource']);
106
-				list($owner, $ownerPath) = $this->getOwnerPath($path);
107
-				$absPath = '/' . $owner . '/files/' . $ownerPath;
108
-				$this->update($absPath);
109
-			}
110
-		}
111
-	}
112
-
113
-	/**
114
-	 * inform encryption module that a file was restored from the trash bin,
115
-	 * e.g. to update the encryption keys
116
-	 *
117
-	 * @param array $params
118
-	 */
119
-	public function postRestore($params) {
120
-		if ($this->encryptionManager->isEnabled()) {
121
-			$path = Filesystem::normalizePath('/' . $this->uid . '/files/' . $params['filePath']);
122
-			$this->update($path);
123
-		}
124
-	}
125
-
126
-	/**
127
-	 * inform encryption module that a file was renamed,
128
-	 * e.g. to update the encryption keys
129
-	 *
130
-	 * @param array $params
131
-	 */
132
-	public function postRename($params) {
133
-		$source = $params['oldpath'];
134
-		$target = $params['newpath'];
135
-		if(
136
-			$this->encryptionManager->isEnabled() &&
137
-			dirname($source) !== dirname($target)
138
-		) {
139
-				list($owner, $ownerPath) = $this->getOwnerPath($target);
140
-				$absPath = '/' . $owner . '/files/' . $ownerPath;
141
-				$this->update($absPath);
142
-		}
143
-	}
144
-
145
-	/**
146
-	 * get owner and path relative to data/<owner>/files
147
-	 *
148
-	 * @param string $path path to file for current user
149
-	 * @return array ['owner' => $owner, 'path' => $path]
150
-	 * @throw \InvalidArgumentException
151
-	 */
152
-	protected function getOwnerPath($path) {
153
-		$info = Filesystem::getFileInfo($path);
154
-		$owner = Filesystem::getOwner($path);
155
-		$view = new View('/' . $owner . '/files');
156
-		$path = $view->getPath($info->getId());
157
-		if ($path === null) {
158
-			throw new \InvalidArgumentException('No file found for ' . $info->getId());
159
-		}
160
-
161
-		return [$owner, $path];
162
-	}
163
-
164
-	/**
165
-	 * notify encryption module about added/removed users from a file/folder
166
-	 *
167
-	 * @param string $path relative to data/
168
-	 * @throws Exceptions\ModuleDoesNotExistsException
169
-	 */
170
-	public function update($path) {
171
-
172
-		$encryptionModule = $this->encryptionManager->getEncryptionModule();
173
-
174
-		// if the encryption module doesn't encrypt the files on a per-user basis
175
-		// we have nothing to do here.
176
-		if ($encryptionModule->needDetailedAccessList() === false) {
177
-			return;
178
-		}
179
-
180
-		// if a folder was shared, get a list of all (sub-)folders
181
-		if ($this->view->is_dir($path)) {
182
-			$allFiles = $this->util->getAllFiles($path);
183
-		} else {
184
-			$allFiles = [$path];
185
-		}
186
-
187
-
188
-
189
-		foreach ($allFiles as $file) {
190
-			$usersSharing = $this->file->getAccessList($file);
191
-			$encryptionModule->update($file, $this->uid, $usersSharing);
192
-		}
193
-	}
37
+    /** @var \OC\Files\View */
38
+    protected $view;
39
+
40
+    /** @var \OC\Encryption\Util */
41
+    protected $util;
42
+
43
+        /** @var \OC\Files\Mount\Manager */
44
+    protected $mountManager;
45
+
46
+    /** @var \OC\Encryption\Manager */
47
+    protected $encryptionManager;
48
+
49
+    /** @var string */
50
+    protected $uid;
51
+
52
+    /** @var \OC\Encryption\File */
53
+    protected $file;
54
+
55
+    /**
56
+     *
57
+     * @param \OC\Files\View $view
58
+     * @param \OC\Encryption\Util $util
59
+     * @param \OC\Files\Mount\Manager $mountManager
60
+     * @param \OC\Encryption\Manager $encryptionManager
61
+     * @param \OC\Encryption\File $file
62
+     * @param string $uid
63
+     */
64
+    public function __construct(
65
+            View $view,
66
+            Util $util,
67
+            Mount\Manager $mountManager,
68
+            Manager $encryptionManager,
69
+            File $file,
70
+            $uid
71
+        ) {
72
+
73
+        $this->view = $view;
74
+        $this->util = $util;
75
+        $this->mountManager = $mountManager;
76
+        $this->encryptionManager = $encryptionManager;
77
+        $this->file = $file;
78
+        $this->uid = $uid;
79
+    }
80
+
81
+    /**
82
+     * hook after file was shared
83
+     *
84
+     * @param array $params
85
+     */
86
+    public function postShared($params) {
87
+        if ($this->encryptionManager->isEnabled()) {
88
+            if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
89
+                $path = Filesystem::getPath($params['fileSource']);
90
+                list($owner, $ownerPath) = $this->getOwnerPath($path);
91
+                $absPath = '/' . $owner . '/files/' . $ownerPath;
92
+                $this->update($absPath);
93
+            }
94
+        }
95
+    }
96
+
97
+    /**
98
+     * hook after file was unshared
99
+     *
100
+     * @param array $params
101
+     */
102
+    public function postUnshared($params) {
103
+        if ($this->encryptionManager->isEnabled()) {
104
+            if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
105
+                $path = Filesystem::getPath($params['fileSource']);
106
+                list($owner, $ownerPath) = $this->getOwnerPath($path);
107
+                $absPath = '/' . $owner . '/files/' . $ownerPath;
108
+                $this->update($absPath);
109
+            }
110
+        }
111
+    }
112
+
113
+    /**
114
+     * inform encryption module that a file was restored from the trash bin,
115
+     * e.g. to update the encryption keys
116
+     *
117
+     * @param array $params
118
+     */
119
+    public function postRestore($params) {
120
+        if ($this->encryptionManager->isEnabled()) {
121
+            $path = Filesystem::normalizePath('/' . $this->uid . '/files/' . $params['filePath']);
122
+            $this->update($path);
123
+        }
124
+    }
125
+
126
+    /**
127
+     * inform encryption module that a file was renamed,
128
+     * e.g. to update the encryption keys
129
+     *
130
+     * @param array $params
131
+     */
132
+    public function postRename($params) {
133
+        $source = $params['oldpath'];
134
+        $target = $params['newpath'];
135
+        if(
136
+            $this->encryptionManager->isEnabled() &&
137
+            dirname($source) !== dirname($target)
138
+        ) {
139
+                list($owner, $ownerPath) = $this->getOwnerPath($target);
140
+                $absPath = '/' . $owner . '/files/' . $ownerPath;
141
+                $this->update($absPath);
142
+        }
143
+    }
144
+
145
+    /**
146
+     * get owner and path relative to data/<owner>/files
147
+     *
148
+     * @param string $path path to file for current user
149
+     * @return array ['owner' => $owner, 'path' => $path]
150
+     * @throw \InvalidArgumentException
151
+     */
152
+    protected function getOwnerPath($path) {
153
+        $info = Filesystem::getFileInfo($path);
154
+        $owner = Filesystem::getOwner($path);
155
+        $view = new View('/' . $owner . '/files');
156
+        $path = $view->getPath($info->getId());
157
+        if ($path === null) {
158
+            throw new \InvalidArgumentException('No file found for ' . $info->getId());
159
+        }
160
+
161
+        return [$owner, $path];
162
+    }
163
+
164
+    /**
165
+     * notify encryption module about added/removed users from a file/folder
166
+     *
167
+     * @param string $path relative to data/
168
+     * @throws Exceptions\ModuleDoesNotExistsException
169
+     */
170
+    public function update($path) {
171
+
172
+        $encryptionModule = $this->encryptionManager->getEncryptionModule();
173
+
174
+        // if the encryption module doesn't encrypt the files on a per-user basis
175
+        // we have nothing to do here.
176
+        if ($encryptionModule->needDetailedAccessList() === false) {
177
+            return;
178
+        }
179
+
180
+        // if a folder was shared, get a list of all (sub-)folders
181
+        if ($this->view->is_dir($path)) {
182
+            $allFiles = $this->util->getAllFiles($path);
183
+        } else {
184
+            $allFiles = [$path];
185
+        }
186
+
187
+
188
+
189
+        foreach ($allFiles as $file) {
190
+            $usersSharing = $this->file->getAccessList($file);
191
+            $encryptionModule->update($file, $this->uid, $usersSharing);
192
+        }
193
+    }
194 194
 
195 195
 }
Please login to merge, or discard this patch.
lib/private/legacy/app.php 1 patch
Indentation   +1052 added lines, -1052 removed lines patch added patch discarded remove patch
@@ -65,1056 +65,1056 @@
 block discarded – undo
65 65
  * upgrading and removing apps.
66 66
  */
67 67
 class OC_App {
68
-	static private $adminForms = [];
69
-	static private $personalForms = [];
70
-	static private $appTypes = [];
71
-	static private $loadedApps = [];
72
-	static private $altLogin = [];
73
-	static private $alreadyRegistered = [];
74
-	const supportedApp = 300;
75
-	const officialApp = 200;
76
-
77
-	/**
78
-	 * clean the appId
79
-	 *
80
-	 * @param string $app AppId that needs to be cleaned
81
-	 * @return string
82
-	 */
83
-	public static function cleanAppId(string $app): string {
84
-		return str_replace(['\0', '/', '\\', '..'], '', $app);
85
-	}
86
-
87
-	/**
88
-	 * Check if an app is loaded
89
-	 *
90
-	 * @param string $app
91
-	 * @return bool
92
-	 */
93
-	public static function isAppLoaded(string $app): bool {
94
-		return in_array($app, self::$loadedApps, true);
95
-	}
96
-
97
-	/**
98
-	 * loads all apps
99
-	 *
100
-	 * @param string[] $types
101
-	 * @return bool
102
-	 *
103
-	 * This function walks through the ownCloud directory and loads all apps
104
-	 * it can find. A directory contains an app if the file /appinfo/info.xml
105
-	 * exists.
106
-	 *
107
-	 * if $types is set to non-empty array, only apps of those types will be loaded
108
-	 */
109
-	public static function loadApps(array $types = []): bool {
110
-		if ((bool) \OC::$server->getSystemConfig()->getValue('maintenance', false)) {
111
-			return false;
112
-		}
113
-		// Load the enabled apps here
114
-		$apps = self::getEnabledApps();
115
-
116
-		// Add each apps' folder as allowed class path
117
-		foreach($apps as $app) {
118
-			$path = self::getAppPath($app);
119
-			if($path !== false) {
120
-				self::registerAutoloading($app, $path);
121
-			}
122
-		}
123
-
124
-		// prevent app.php from printing output
125
-		ob_start();
126
-		foreach ($apps as $app) {
127
-			if (($types === [] or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) {
128
-				self::loadApp($app);
129
-			}
130
-		}
131
-		ob_end_clean();
132
-
133
-		return true;
134
-	}
135
-
136
-	/**
137
-	 * load a single app
138
-	 *
139
-	 * @param string $app
140
-	 * @throws Exception
141
-	 */
142
-	public static function loadApp(string $app) {
143
-		self::$loadedApps[] = $app;
144
-		$appPath = self::getAppPath($app);
145
-		if($appPath === false) {
146
-			return;
147
-		}
148
-
149
-		// in case someone calls loadApp() directly
150
-		self::registerAutoloading($app, $appPath);
151
-
152
-		if (is_file($appPath . '/appinfo/app.php')) {
153
-			\OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
154
-			try {
155
-				self::requireAppFile($app);
156
-			} catch (Throwable $ex) {
157
-				if($ex instanceof ServerNotAvailableException) {
158
-					throw $ex;
159
-				}
160
-				\OC::$server->getLogger()->logException($ex);
161
-
162
-				if (!\OC::$server->getAppManager()->isShipped($app) && !self::isType($app, ['authentication'])) {
163
-					// Only disable apps which are not shipped and that are not authentication apps
164
-					\OC::$server->getAppManager()->disableApp($app, true);
165
-				}
166
-			}
167
-			\OC::$server->getEventLogger()->end('load_app_' . $app);
168
-		}
169
-
170
-		$info = self::getAppInfo($app);
171
-		if (!empty($info['activity']['filters'])) {
172
-			foreach ($info['activity']['filters'] as $filter) {
173
-				\OC::$server->getActivityManager()->registerFilter($filter);
174
-			}
175
-		}
176
-		if (!empty($info['activity']['settings'])) {
177
-			foreach ($info['activity']['settings'] as $setting) {
178
-				\OC::$server->getActivityManager()->registerSetting($setting);
179
-			}
180
-		}
181
-		if (!empty($info['activity']['providers'])) {
182
-			foreach ($info['activity']['providers'] as $provider) {
183
-				\OC::$server->getActivityManager()->registerProvider($provider);
184
-			}
185
-		}
186
-
187
-		if (!empty($info['settings']['admin'])) {
188
-			foreach ($info['settings']['admin'] as $setting) {
189
-				\OC::$server->getSettingsManager()->registerSetting('admin', $setting);
190
-			}
191
-		}
192
-		if (!empty($info['settings']['admin-section'])) {
193
-			foreach ($info['settings']['admin-section'] as $section) {
194
-				\OC::$server->getSettingsManager()->registerSection('admin', $section);
195
-			}
196
-		}
197
-		if (!empty($info['settings']['personal'])) {
198
-			foreach ($info['settings']['personal'] as $setting) {
199
-				\OC::$server->getSettingsManager()->registerSetting('personal', $setting);
200
-			}
201
-		}
202
-		if (!empty($info['settings']['personal-section'])) {
203
-			foreach ($info['settings']['personal-section'] as $section) {
204
-				\OC::$server->getSettingsManager()->registerSection('personal', $section);
205
-			}
206
-		}
207
-
208
-		if (!empty($info['collaboration']['plugins'])) {
209
-			// deal with one or many plugin entries
210
-			$plugins = isset($info['collaboration']['plugins']['plugin']['@value']) ?
211
-				[$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin'];
212
-			foreach ($plugins as $plugin) {
213
-				if($plugin['@attributes']['type'] === 'collaborator-search') {
214
-					$pluginInfo = [
215
-						'shareType' => $plugin['@attributes']['share-type'],
216
-						'class' => $plugin['@value'],
217
-					];
218
-					\OC::$server->getCollaboratorSearch()->registerPlugin($pluginInfo);
219
-				} else if ($plugin['@attributes']['type'] === 'autocomplete-sort') {
220
-					\OC::$server->getAutoCompleteManager()->registerSorter($plugin['@value']);
221
-				}
222
-			}
223
-		}
224
-	}
225
-
226
-	/**
227
-	 * @internal
228
-	 * @param string $app
229
-	 * @param string $path
230
-	 * @param bool $force
231
-	 */
232
-	public static function registerAutoloading(string $app, string $path, bool $force = false) {
233
-		$key = $app . '-' . $path;
234
-		if (!$force && isset(self::$alreadyRegistered[$key])) {
235
-			return;
236
-		}
237
-
238
-		self::$alreadyRegistered[$key] = true;
239
-
240
-		// Register on PSR-4 composer autoloader
241
-		$appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
242
-		\OC::$server->registerNamespace($app, $appNamespace);
243
-
244
-		if (file_exists($path . '/composer/autoload.php')) {
245
-			require_once $path . '/composer/autoload.php';
246
-		} else {
247
-			\OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
248
-			// Register on legacy autoloader
249
-			\OC::$loader->addValidRoot($path);
250
-		}
251
-
252
-		// Register Test namespace only when testing
253
-		if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
254
-			\OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);
255
-		}
256
-	}
257
-
258
-	/**
259
-	 * Load app.php from the given app
260
-	 *
261
-	 * @param string $app app name
262
-	 * @throws Error
263
-	 */
264
-	private static function requireAppFile(string $app) {
265
-		// encapsulated here to avoid variable scope conflicts
266
-		require_once $app . '/appinfo/app.php';
267
-	}
268
-
269
-	/**
270
-	 * check if an app is of a specific type
271
-	 *
272
-	 * @param string $app
273
-	 * @param array $types
274
-	 * @return bool
275
-	 */
276
-	public static function isType(string $app, array $types): bool {
277
-		$appTypes = self::getAppTypes($app);
278
-		foreach ($types as $type) {
279
-			if (array_search($type, $appTypes) !== false) {
280
-				return true;
281
-			}
282
-		}
283
-		return false;
284
-	}
285
-
286
-	/**
287
-	 * get the types of an app
288
-	 *
289
-	 * @param string $app
290
-	 * @return array
291
-	 */
292
-	private static function getAppTypes(string $app): array {
293
-		//load the cache
294
-		if (count(self::$appTypes) == 0) {
295
-			self::$appTypes = \OC::$server->getAppConfig()->getValues(false, 'types');
296
-		}
297
-
298
-		if (isset(self::$appTypes[$app])) {
299
-			return explode(',', self::$appTypes[$app]);
300
-		}
301
-
302
-		return [];
303
-	}
304
-
305
-	/**
306
-	 * read app types from info.xml and cache them in the database
307
-	 */
308
-	public static function setAppTypes(string $app) {
309
-		$appManager = \OC::$server->getAppManager();
310
-		$appData = $appManager->getAppInfo($app);
311
-		if(!is_array($appData)) {
312
-			return;
313
-		}
314
-
315
-		if (isset($appData['types'])) {
316
-			$appTypes = implode(',', $appData['types']);
317
-		} else {
318
-			$appTypes = '';
319
-			$appData['types'] = [];
320
-		}
321
-
322
-		$config = \OC::$server->getConfig();
323
-		$config->setAppValue($app, 'types', $appTypes);
324
-
325
-		if ($appManager->hasProtectedAppType($appData['types'])) {
326
-			$enabled = $config->getAppValue($app, 'enabled', 'yes');
327
-			if ($enabled !== 'yes' && $enabled !== 'no') {
328
-				$config->setAppValue($app, 'enabled', 'yes');
329
-			}
330
-		}
331
-	}
332
-
333
-	/**
334
-	 * Returns apps enabled for the current user.
335
-	 *
336
-	 * @param bool $forceRefresh whether to refresh the cache
337
-	 * @param bool $all whether to return apps for all users, not only the
338
-	 * currently logged in one
339
-	 * @return string[]
340
-	 */
341
-	public static function getEnabledApps(bool $forceRefresh = false, bool $all = false): array {
342
-		if (!\OC::$server->getSystemConfig()->getValue('installed', false)) {
343
-			return [];
344
-		}
345
-		// in incognito mode or when logged out, $user will be false,
346
-		// which is also the case during an upgrade
347
-		$appManager = \OC::$server->getAppManager();
348
-		if ($all) {
349
-			$user = null;
350
-		} else {
351
-			$user = \OC::$server->getUserSession()->getUser();
352
-		}
353
-
354
-		if (is_null($user)) {
355
-			$apps = $appManager->getInstalledApps();
356
-		} else {
357
-			$apps = $appManager->getEnabledAppsForUser($user);
358
-		}
359
-		$apps = array_filter($apps, function ($app) {
360
-			return $app !== 'files';//we add this manually
361
-		});
362
-		sort($apps);
363
-		array_unshift($apps, 'files');
364
-		return $apps;
365
-	}
366
-
367
-	/**
368
-	 * checks whether or not an app is enabled
369
-	 *
370
-	 * @param string $app app
371
-	 * @return bool
372
-	 * @deprecated 13.0.0 use \OC::$server->getAppManager()->isEnabledForUser($appId)
373
-	 *
374
-	 * This function checks whether or not an app is enabled.
375
-	 */
376
-	public static function isEnabled(string $app): bool {
377
-		return \OC::$server->getAppManager()->isEnabledForUser($app);
378
-	}
379
-
380
-	/**
381
-	 * enables an app
382
-	 *
383
-	 * @param string $appId
384
-	 * @param array $groups (optional) when set, only these groups will have access to the app
385
-	 * @throws \Exception
386
-	 * @return void
387
-	 *
388
-	 * This function set an app as enabled in appconfig.
389
-	 */
390
-	public function enable(string $appId,
391
-						   array $groups = []) {
392
-
393
-		// Check if app is already downloaded
394
-		/** @var Installer $installer */
395
-		$installer = \OC::$server->query(Installer::class);
396
-		$isDownloaded = $installer->isDownloaded($appId);
397
-
398
-		if(!$isDownloaded) {
399
-			$installer->downloadApp($appId);
400
-		}
401
-
402
-		$installer->installApp($appId);
403
-
404
-		$appManager = \OC::$server->getAppManager();
405
-		if ($groups !== []) {
406
-			$groupManager = \OC::$server->getGroupManager();
407
-			$groupsList = [];
408
-			foreach ($groups as $group) {
409
-				$groupItem = $groupManager->get($group);
410
-				if ($groupItem instanceof \OCP\IGroup) {
411
-					$groupsList[] = $groupManager->get($group);
412
-				}
413
-			}
414
-			$appManager->enableAppForGroups($appId, $groupsList);
415
-		} else {
416
-			$appManager->enableApp($appId);
417
-		}
418
-	}
419
-
420
-	/**
421
-	 * Get the path where to install apps
422
-	 *
423
-	 * @return string|false
424
-	 */
425
-	public static function getInstallPath() {
426
-		if (\OC::$server->getSystemConfig()->getValue('appstoreenabled', true) == false) {
427
-			return false;
428
-		}
429
-
430
-		foreach (OC::$APPSROOTS as $dir) {
431
-			if (isset($dir['writable']) && $dir['writable'] === true) {
432
-				return $dir['path'];
433
-			}
434
-		}
435
-
436
-		\OCP\Util::writeLog('core', 'No application directories are marked as writable.', ILogger::ERROR);
437
-		return null;
438
-	}
439
-
440
-
441
-	/**
442
-	 * search for an app in all app-directories
443
-	 *
444
-	 * @param string $appId
445
-	 * @return false|string
446
-	 */
447
-	public static function findAppInDirectories(string $appId) {
448
-		$sanitizedAppId = self::cleanAppId($appId);
449
-		if($sanitizedAppId !== $appId) {
450
-			return false;
451
-		}
452
-		static $app_dir = [];
453
-
454
-		if (isset($app_dir[$appId])) {
455
-			return $app_dir[$appId];
456
-		}
457
-
458
-		$possibleApps = [];
459
-		foreach (OC::$APPSROOTS as $dir) {
460
-			if (file_exists($dir['path'] . '/' . $appId)) {
461
-				$possibleApps[] = $dir;
462
-			}
463
-		}
464
-
465
-		if (empty($possibleApps)) {
466
-			return false;
467
-		} elseif (count($possibleApps) === 1) {
468
-			$dir = array_shift($possibleApps);
469
-			$app_dir[$appId] = $dir;
470
-			return $dir;
471
-		} else {
472
-			$versionToLoad = [];
473
-			foreach ($possibleApps as $possibleApp) {
474
-				$version = self::getAppVersionByPath($possibleApp['path'] . '/' . $appId);
475
-				if (empty($versionToLoad) || version_compare($version, $versionToLoad['version'], '>')) {
476
-					$versionToLoad = [
477
-						'dir' => $possibleApp,
478
-						'version' => $version,
479
-					];
480
-				}
481
-			}
482
-			$app_dir[$appId] = $versionToLoad['dir'];
483
-			return $versionToLoad['dir'];
484
-			//TODO - write test
485
-		}
486
-	}
487
-
488
-	/**
489
-	 * Get the directory for the given app.
490
-	 * If the app is defined in multiple directories, the first one is taken. (false if not found)
491
-	 *
492
-	 * @param string $appId
493
-	 * @return string|false
494
-	 * @deprecated 11.0.0 use \OC::$server->getAppManager()->getAppPath()
495
-	 */
496
-	public static function getAppPath(string $appId) {
497
-		if ($appId === null || trim($appId) === '') {
498
-			return false;
499
-		}
500
-
501
-		if (($dir = self::findAppInDirectories($appId)) != false) {
502
-			return $dir['path'] . '/' . $appId;
503
-		}
504
-		return false;
505
-	}
506
-
507
-	/**
508
-	 * Get the path for the given app on the access
509
-	 * If the app is defined in multiple directories, the first one is taken. (false if not found)
510
-	 *
511
-	 * @param string $appId
512
-	 * @return string|false
513
-	 * @deprecated 18.0.0 use \OC::$server->getAppManager()->getAppWebPath()
514
-	 */
515
-	public static function getAppWebPath(string $appId) {
516
-		if (($dir = self::findAppInDirectories($appId)) != false) {
517
-			return OC::$WEBROOT . $dir['url'] . '/' . $appId;
518
-		}
519
-		return false;
520
-	}
521
-
522
-	/**
523
-	 * get the last version of the app from appinfo/info.xml
524
-	 *
525
-	 * @param string $appId
526
-	 * @param bool $useCache
527
-	 * @return string
528
-	 * @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppVersion()
529
-	 */
530
-	public static function getAppVersion(string $appId, bool $useCache = true): string {
531
-		return \OC::$server->getAppManager()->getAppVersion($appId, $useCache);
532
-	}
533
-
534
-	/**
535
-	 * get app's version based on it's path
536
-	 *
537
-	 * @param string $path
538
-	 * @return string
539
-	 */
540
-	public static function getAppVersionByPath(string $path): string {
541
-		$infoFile = $path . '/appinfo/info.xml';
542
-		$appData = \OC::$server->getAppManager()->getAppInfo($infoFile, true);
543
-		return isset($appData['version']) ? $appData['version'] : '';
544
-	}
545
-
546
-
547
-	/**
548
-	 * Read all app metadata from the info.xml file
549
-	 *
550
-	 * @param string $appId id of the app or the path of the info.xml file
551
-	 * @param bool $path
552
-	 * @param string $lang
553
-	 * @return array|null
554
-	 * @note all data is read from info.xml, not just pre-defined fields
555
-	 * @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppInfo()
556
-	 */
557
-	public static function getAppInfo(string $appId, bool $path = false, string $lang = null) {
558
-		return \OC::$server->getAppManager()->getAppInfo($appId, $path, $lang);
559
-	}
560
-
561
-	/**
562
-	 * Returns the navigation
563
-	 *
564
-	 * @return array
565
-	 * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll()
566
-	 *
567
-	 * This function returns an array containing all entries added. The
568
-	 * entries are sorted by the key 'order' ascending. Additional to the keys
569
-	 * given for each app the following keys exist:
570
-	 *   - active: boolean, signals if the user is on this navigation entry
571
-	 */
572
-	public static function getNavigation(): array {
573
-		return OC::$server->getNavigationManager()->getAll();
574
-	}
575
-
576
-	/**
577
-	 * Returns the Settings Navigation
578
-	 *
579
-	 * @return string[]
580
-	 * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll('settings')
581
-	 *
582
-	 * This function returns an array containing all settings pages added. The
583
-	 * entries are sorted by the key 'order' ascending.
584
-	 */
585
-	public static function getSettingsNavigation(): array {
586
-		return OC::$server->getNavigationManager()->getAll('settings');
587
-	}
588
-
589
-	/**
590
-	 * get the id of loaded app
591
-	 *
592
-	 * @return string
593
-	 */
594
-	public static function getCurrentApp(): string {
595
-		$request = \OC::$server->getRequest();
596
-		$script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1);
597
-		$topFolder = substr($script, 0, strpos($script, '/') ?: 0);
598
-		if (empty($topFolder)) {
599
-			$path_info = $request->getPathInfo();
600
-			if ($path_info) {
601
-				$topFolder = substr($path_info, 1, strpos($path_info, '/', 1) - 1);
602
-			}
603
-		}
604
-		if ($topFolder == 'apps') {
605
-			$length = strlen($topFolder);
606
-			return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1) ?: '';
607
-		} else {
608
-			return $topFolder;
609
-		}
610
-	}
611
-
612
-	/**
613
-	 * @param string $type
614
-	 * @return array
615
-	 */
616
-	public static function getForms(string $type): array {
617
-		$forms = [];
618
-		switch ($type) {
619
-			case 'admin':
620
-				$source = self::$adminForms;
621
-				break;
622
-			case 'personal':
623
-				$source = self::$personalForms;
624
-				break;
625
-			default:
626
-				return [];
627
-		}
628
-		foreach ($source as $form) {
629
-			$forms[] = include $form;
630
-		}
631
-		return $forms;
632
-	}
633
-
634
-	/**
635
-	 * register an admin form to be shown
636
-	 *
637
-	 * @param string $app
638
-	 * @param string $page
639
-	 */
640
-	public static function registerAdmin(string $app, string $page) {
641
-		self::$adminForms[] = $app . '/' . $page . '.php';
642
-	}
643
-
644
-	/**
645
-	 * register a personal form to be shown
646
-	 * @param string $app
647
-	 * @param string $page
648
-	 */
649
-	public static function registerPersonal(string $app, string $page) {
650
-		self::$personalForms[] = $app . '/' . $page . '.php';
651
-	}
652
-
653
-	/**
654
-	 * @param array $entry
655
-	 */
656
-	public static function registerLogIn(array $entry) {
657
-		self::$altLogin[] = $entry;
658
-	}
659
-
660
-	/**
661
-	 * @return array
662
-	 */
663
-	public static function getAlternativeLogIns(): array {
664
-		return self::$altLogin;
665
-	}
666
-
667
-	/**
668
-	 * get a list of all apps in the apps folder
669
-	 *
670
-	 * @return array an array of app names (string IDs)
671
-	 * @todo: change the name of this method to getInstalledApps, which is more accurate
672
-	 */
673
-	public static function getAllApps(): array {
674
-
675
-		$apps = [];
676
-
677
-		foreach (OC::$APPSROOTS as $apps_dir) {
678
-			if (!is_readable($apps_dir['path'])) {
679
-				\OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], ILogger::WARN);
680
-				continue;
681
-			}
682
-			$dh = opendir($apps_dir['path']);
683
-
684
-			if (is_resource($dh)) {
685
-				while (($file = readdir($dh)) !== false) {
686
-
687
-					if ($file[0] != '.' and is_dir($apps_dir['path'] . '/' . $file) and is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml')) {
688
-
689
-						$apps[] = $file;
690
-					}
691
-				}
692
-			}
693
-		}
694
-
695
-		$apps = array_unique($apps);
696
-
697
-		return $apps;
698
-	}
699
-
700
-	/**
701
-	 * List all apps, this is used in apps.php
702
-	 *
703
-	 * @return array
704
-	 */
705
-	public function listAllApps(): array {
706
-		$installedApps = OC_App::getAllApps();
707
-
708
-		$appManager = \OC::$server->getAppManager();
709
-		//we don't want to show configuration for these
710
-		$blacklist = $appManager->getAlwaysEnabledApps();
711
-		$appList = [];
712
-		$langCode = \OC::$server->getL10N('core')->getLanguageCode();
713
-		$urlGenerator = \OC::$server->getURLGenerator();
714
-		/** @var \OCP\Support\Subscription\IRegistry $subscriptionRegistry */
715
-		$subscriptionRegistry = \OC::$server->query(\OCP\Support\Subscription\IRegistry::class);
716
-		$supportedApps = $subscriptionRegistry->delegateGetSupportedApps();
717
-
718
-		foreach ($installedApps as $app) {
719
-			if (array_search($app, $blacklist) === false) {
720
-
721
-				$info = OC_App::getAppInfo($app, false, $langCode);
722
-				if (!is_array($info)) {
723
-					\OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', ILogger::ERROR);
724
-					continue;
725
-				}
726
-
727
-				if (!isset($info['name'])) {
728
-					\OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', ILogger::ERROR);
729
-					continue;
730
-				}
731
-
732
-				$enabled = \OC::$server->getConfig()->getAppValue($app, 'enabled', 'no');
733
-				$info['groups'] = null;
734
-				if ($enabled === 'yes') {
735
-					$active = true;
736
-				} else if ($enabled === 'no') {
737
-					$active = false;
738
-				} else {
739
-					$active = true;
740
-					$info['groups'] = $enabled;
741
-				}
742
-
743
-				$info['active'] = $active;
744
-
745
-				if ($appManager->isShipped($app)) {
746
-					$info['internal'] = true;
747
-					$info['level'] = self::officialApp;
748
-					$info['removable'] = false;
749
-				} else {
750
-					$info['internal'] = false;
751
-					$info['removable'] = true;
752
-				}
753
-
754
-				if (in_array($app, $supportedApps)) {
755
-					$info['level'] = self::supportedApp;
756
-				}
757
-
758
-				$appPath = self::getAppPath($app);
759
-				if($appPath !== false) {
760
-					$appIcon = $appPath . '/img/' . $app . '.svg';
761
-					if (file_exists($appIcon)) {
762
-						$info['preview'] = $urlGenerator->imagePath($app, $app . '.svg');
763
-						$info['previewAsIcon'] = true;
764
-					} else {
765
-						$appIcon = $appPath . '/img/app.svg';
766
-						if (file_exists($appIcon)) {
767
-							$info['preview'] = $urlGenerator->imagePath($app, 'app.svg');
768
-							$info['previewAsIcon'] = true;
769
-						}
770
-					}
771
-				}
772
-				// fix documentation
773
-				if (isset($info['documentation']) && is_array($info['documentation'])) {
774
-					foreach ($info['documentation'] as $key => $url) {
775
-						// If it is not an absolute URL we assume it is a key
776
-						// i.e. admin-ldap will get converted to go.php?to=admin-ldap
777
-						if (stripos($url, 'https://') !== 0 && stripos($url, 'http://') !== 0) {
778
-							$url = $urlGenerator->linkToDocs($url);
779
-						}
780
-
781
-						$info['documentation'][$key] = $url;
782
-					}
783
-				}
784
-
785
-				$info['version'] = OC_App::getAppVersion($app);
786
-				$appList[] = $info;
787
-			}
788
-		}
789
-
790
-		return $appList;
791
-	}
792
-
793
-	public static function shouldUpgrade(string $app): bool {
794
-		$versions = self::getAppVersions();
795
-		$currentVersion = OC_App::getAppVersion($app);
796
-		if ($currentVersion && isset($versions[$app])) {
797
-			$installedVersion = $versions[$app];
798
-			if (!version_compare($currentVersion, $installedVersion, '=')) {
799
-				return true;
800
-			}
801
-		}
802
-		return false;
803
-	}
804
-
805
-	/**
806
-	 * Adjust the number of version parts of $version1 to match
807
-	 * the number of version parts of $version2.
808
-	 *
809
-	 * @param string $version1 version to adjust
810
-	 * @param string $version2 version to take the number of parts from
811
-	 * @return string shortened $version1
812
-	 */
813
-	private static function adjustVersionParts(string $version1, string $version2): string {
814
-		$version1 = explode('.', $version1);
815
-		$version2 = explode('.', $version2);
816
-		// reduce $version1 to match the number of parts in $version2
817
-		while (count($version1) > count($version2)) {
818
-			array_pop($version1);
819
-		}
820
-		// if $version1 does not have enough parts, add some
821
-		while (count($version1) < count($version2)) {
822
-			$version1[] = '0';
823
-		}
824
-		return implode('.', $version1);
825
-	}
826
-
827
-	/**
828
-	 * Check whether the current ownCloud version matches the given
829
-	 * application's version requirements.
830
-	 *
831
-	 * The comparison is made based on the number of parts that the
832
-	 * app info version has. For example for ownCloud 6.0.3 if the
833
-	 * app info version is expecting version 6.0, the comparison is
834
-	 * made on the first two parts of the ownCloud version.
835
-	 * This means that it's possible to specify "requiremin" => 6
836
-	 * and "requiremax" => 6 and it will still match ownCloud 6.0.3.
837
-	 *
838
-	 * @param string $ocVersion ownCloud version to check against
839
-	 * @param array $appInfo app info (from xml)
840
-	 *
841
-	 * @return boolean true if compatible, otherwise false
842
-	 */
843
-	public static function isAppCompatible(string $ocVersion, array $appInfo, bool $ignoreMax = false): bool {
844
-		$requireMin = '';
845
-		$requireMax = '';
846
-		if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) {
847
-			$requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version'];
848
-		} elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) {
849
-			$requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version'];
850
-		} else if (isset($appInfo['requiremin'])) {
851
-			$requireMin = $appInfo['requiremin'];
852
-		} else if (isset($appInfo['require'])) {
853
-			$requireMin = $appInfo['require'];
854
-		}
855
-
856
-		if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) {
857
-			$requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version'];
858
-		} elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) {
859
-			$requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version'];
860
-		} else if (isset($appInfo['requiremax'])) {
861
-			$requireMax = $appInfo['requiremax'];
862
-		}
863
-
864
-		if (!empty($requireMin)
865
-			&& version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<')
866
-		) {
867
-
868
-			return false;
869
-		}
870
-
871
-		if (!$ignoreMax && !empty($requireMax)
872
-			&& version_compare(self::adjustVersionParts($ocVersion, $requireMax), $requireMax, '>')
873
-		) {
874
-			return false;
875
-		}
876
-
877
-		return true;
878
-	}
879
-
880
-	/**
881
-	 * get the installed version of all apps
882
-	 */
883
-	public static function getAppVersions() {
884
-		static $versions;
885
-
886
-		if(!$versions) {
887
-			$appConfig = \OC::$server->getAppConfig();
888
-			$versions = $appConfig->getValues(false, 'installed_version');
889
-		}
890
-		return $versions;
891
-	}
892
-
893
-	/**
894
-	 * update the database for the app and call the update script
895
-	 *
896
-	 * @param string $appId
897
-	 * @return bool
898
-	 */
899
-	public static function updateApp(string $appId): bool {
900
-		$appPath = self::getAppPath($appId);
901
-		if($appPath === false) {
902
-			return false;
903
-		}
904
-
905
-		\OC::$server->getAppManager()->clearAppsCache();
906
-		$appData = self::getAppInfo($appId);
907
-
908
-		self::registerAutoloading($appId, $appPath, true);
909
-		self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
910
-
911
-		if (file_exists($appPath . '/appinfo/database.xml')) {
912
-			OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
913
-		} else {
914
-			$ms = new MigrationService($appId, \OC::$server->getDatabaseConnection());
915
-			$ms->migrate();
916
-		}
917
-
918
-		self::executeRepairSteps($appId, $appData['repair-steps']['post-migration']);
919
-		self::setupLiveMigrations($appId, $appData['repair-steps']['live-migration']);
920
-		// update appversion in app manager
921
-		\OC::$server->getAppManager()->clearAppsCache();
922
-		\OC::$server->getAppManager()->getAppVersion($appId, false);
923
-
924
-		// run upgrade code
925
-		if (file_exists($appPath . '/appinfo/update.php')) {
926
-			self::loadApp($appId);
927
-			include $appPath . '/appinfo/update.php';
928
-		}
929
-		self::setupBackgroundJobs($appData['background-jobs']);
930
-
931
-		//set remote/public handlers
932
-		if (array_key_exists('ocsid', $appData)) {
933
-			\OC::$server->getConfig()->setAppValue($appId, 'ocsid', $appData['ocsid']);
934
-		} elseif(\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
935
-			\OC::$server->getConfig()->deleteAppValue($appId, 'ocsid');
936
-		}
937
-		foreach ($appData['remote'] as $name => $path) {
938
-			\OC::$server->getConfig()->setAppValue('core', 'remote_' . $name, $appId . '/' . $path);
939
-		}
940
-		foreach ($appData['public'] as $name => $path) {
941
-			\OC::$server->getConfig()->setAppValue('core', 'public_' . $name, $appId . '/' . $path);
942
-		}
943
-
944
-		self::setAppTypes($appId);
945
-
946
-		$version = \OC_App::getAppVersion($appId);
947
-		\OC::$server->getConfig()->setAppValue($appId, 'installed_version', $version);
948
-
949
-		\OC::$server->getEventDispatcher()->dispatch(ManagerEvent::EVENT_APP_UPDATE, new ManagerEvent(
950
-			ManagerEvent::EVENT_APP_UPDATE, $appId
951
-		));
952
-
953
-		return true;
954
-	}
955
-
956
-	/**
957
-	 * @param string $appId
958
-	 * @param string[] $steps
959
-	 * @throws \OC\NeedsUpdateException
960
-	 */
961
-	public static function executeRepairSteps(string $appId, array $steps) {
962
-		if (empty($steps)) {
963
-			return;
964
-		}
965
-		// load the app
966
-		self::loadApp($appId);
967
-
968
-		$dispatcher = OC::$server->getEventDispatcher();
969
-
970
-		// load the steps
971
-		$r = new Repair([], $dispatcher);
972
-		foreach ($steps as $step) {
973
-			try {
974
-				$r->addStep($step);
975
-			} catch (Exception $ex) {
976
-				$r->emit('\OC\Repair', 'error', [$ex->getMessage()]);
977
-				\OC::$server->getLogger()->logException($ex);
978
-			}
979
-		}
980
-		// run the steps
981
-		$r->run();
982
-	}
983
-
984
-	public static function setupBackgroundJobs(array $jobs) {
985
-		$queue = \OC::$server->getJobList();
986
-		foreach ($jobs as $job) {
987
-			$queue->add($job);
988
-		}
989
-	}
990
-
991
-	/**
992
-	 * @param string $appId
993
-	 * @param string[] $steps
994
-	 */
995
-	private static function setupLiveMigrations(string $appId, array $steps) {
996
-		$queue = \OC::$server->getJobList();
997
-		foreach ($steps as $step) {
998
-			$queue->add('OC\Migration\BackgroundRepair', [
999
-				'app' => $appId,
1000
-				'step' => $step]);
1001
-		}
1002
-	}
1003
-
1004
-	/**
1005
-	 * @param string $appId
1006
-	 * @return \OC\Files\View|false
1007
-	 */
1008
-	public static function getStorage(string $appId) {
1009
-		if (\OC::$server->getAppManager()->isEnabledForUser($appId)) { //sanity check
1010
-			if (\OC::$server->getUserSession()->isLoggedIn()) {
1011
-				$view = new \OC\Files\View('/' . OC_User::getUser());
1012
-				if (!$view->file_exists($appId)) {
1013
-					$view->mkdir($appId);
1014
-				}
1015
-				return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
1016
-			} else {
1017
-				\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', ILogger::ERROR);
1018
-				return false;
1019
-			}
1020
-		} else {
1021
-			\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', ILogger::ERROR);
1022
-			return false;
1023
-		}
1024
-	}
1025
-
1026
-	protected static function findBestL10NOption(array $options, string $lang): string {
1027
-		// only a single option
1028
-		if (isset($options['@value'])) {
1029
-			return $options['@value'];
1030
-		}
1031
-
1032
-		$fallback = $similarLangFallback = $englishFallback = false;
1033
-
1034
-		$lang = strtolower($lang);
1035
-		$similarLang = $lang;
1036
-		if (strpos($similarLang, '_')) {
1037
-			// For "de_DE" we want to find "de" and the other way around
1038
-			$similarLang = substr($lang, 0, strpos($lang, '_'));
1039
-		}
1040
-
1041
-		foreach ($options as $option) {
1042
-			if (is_array($option)) {
1043
-				if ($fallback === false) {
1044
-					$fallback = $option['@value'];
1045
-				}
1046
-
1047
-				if (!isset($option['@attributes']['lang'])) {
1048
-					continue;
1049
-				}
1050
-
1051
-				$attributeLang = strtolower($option['@attributes']['lang']);
1052
-				if ($attributeLang === $lang) {
1053
-					return $option['@value'];
1054
-				}
1055
-
1056
-				if ($attributeLang === $similarLang) {
1057
-					$similarLangFallback = $option['@value'];
1058
-				} else if (strpos($attributeLang, $similarLang . '_') === 0) {
1059
-					if ($similarLangFallback === false) {
1060
-						$similarLangFallback =  $option['@value'];
1061
-					}
1062
-				}
1063
-			} else {
1064
-				$englishFallback = $option;
1065
-			}
1066
-		}
1067
-
1068
-		if ($similarLangFallback !== false) {
1069
-			return $similarLangFallback;
1070
-		} else if ($englishFallback !== false) {
1071
-			return $englishFallback;
1072
-		}
1073
-		return (string) $fallback;
1074
-	}
1075
-
1076
-	/**
1077
-	 * parses the app data array and enhanced the 'description' value
1078
-	 *
1079
-	 * @param array $data the app data
1080
-	 * @param string $lang
1081
-	 * @return array improved app data
1082
-	 */
1083
-	public static function parseAppInfo(array $data, $lang = null): array {
1084
-
1085
-		if ($lang && isset($data['name']) && is_array($data['name'])) {
1086
-			$data['name'] = self::findBestL10NOption($data['name'], $lang);
1087
-		}
1088
-		if ($lang && isset($data['summary']) && is_array($data['summary'])) {
1089
-			$data['summary'] = self::findBestL10NOption($data['summary'], $lang);
1090
-		}
1091
-		if ($lang && isset($data['description']) && is_array($data['description'])) {
1092
-			$data['description'] = trim(self::findBestL10NOption($data['description'], $lang));
1093
-		} else if (isset($data['description']) && is_string($data['description'])) {
1094
-			$data['description'] = trim($data['description']);
1095
-		} else  {
1096
-			$data['description'] = '';
1097
-		}
1098
-
1099
-		return $data;
1100
-	}
1101
-
1102
-	/**
1103
-	 * @param \OCP\IConfig $config
1104
-	 * @param \OCP\IL10N $l
1105
-	 * @param array $info
1106
-	 * @throws \Exception
1107
-	 */
1108
-	public static function checkAppDependencies(\OCP\IConfig $config, \OCP\IL10N $l, array $info, bool $ignoreMax) {
1109
-		$dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
1110
-		$missing = $dependencyAnalyzer->analyze($info, $ignoreMax);
1111
-		if (!empty($missing)) {
1112
-			$missingMsg = implode(PHP_EOL, $missing);
1113
-			throw new \Exception(
1114
-				$l->t('App "%1$s" cannot be installed because the following dependencies are not fulfilled: %2$s',
1115
-					[$info['name'], $missingMsg]
1116
-				)
1117
-			);
1118
-		}
1119
-	}
68
+    static private $adminForms = [];
69
+    static private $personalForms = [];
70
+    static private $appTypes = [];
71
+    static private $loadedApps = [];
72
+    static private $altLogin = [];
73
+    static private $alreadyRegistered = [];
74
+    const supportedApp = 300;
75
+    const officialApp = 200;
76
+
77
+    /**
78
+     * clean the appId
79
+     *
80
+     * @param string $app AppId that needs to be cleaned
81
+     * @return string
82
+     */
83
+    public static function cleanAppId(string $app): string {
84
+        return str_replace(['\0', '/', '\\', '..'], '', $app);
85
+    }
86
+
87
+    /**
88
+     * Check if an app is loaded
89
+     *
90
+     * @param string $app
91
+     * @return bool
92
+     */
93
+    public static function isAppLoaded(string $app): bool {
94
+        return in_array($app, self::$loadedApps, true);
95
+    }
96
+
97
+    /**
98
+     * loads all apps
99
+     *
100
+     * @param string[] $types
101
+     * @return bool
102
+     *
103
+     * This function walks through the ownCloud directory and loads all apps
104
+     * it can find. A directory contains an app if the file /appinfo/info.xml
105
+     * exists.
106
+     *
107
+     * if $types is set to non-empty array, only apps of those types will be loaded
108
+     */
109
+    public static function loadApps(array $types = []): bool {
110
+        if ((bool) \OC::$server->getSystemConfig()->getValue('maintenance', false)) {
111
+            return false;
112
+        }
113
+        // Load the enabled apps here
114
+        $apps = self::getEnabledApps();
115
+
116
+        // Add each apps' folder as allowed class path
117
+        foreach($apps as $app) {
118
+            $path = self::getAppPath($app);
119
+            if($path !== false) {
120
+                self::registerAutoloading($app, $path);
121
+            }
122
+        }
123
+
124
+        // prevent app.php from printing output
125
+        ob_start();
126
+        foreach ($apps as $app) {
127
+            if (($types === [] or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) {
128
+                self::loadApp($app);
129
+            }
130
+        }
131
+        ob_end_clean();
132
+
133
+        return true;
134
+    }
135
+
136
+    /**
137
+     * load a single app
138
+     *
139
+     * @param string $app
140
+     * @throws Exception
141
+     */
142
+    public static function loadApp(string $app) {
143
+        self::$loadedApps[] = $app;
144
+        $appPath = self::getAppPath($app);
145
+        if($appPath === false) {
146
+            return;
147
+        }
148
+
149
+        // in case someone calls loadApp() directly
150
+        self::registerAutoloading($app, $appPath);
151
+
152
+        if (is_file($appPath . '/appinfo/app.php')) {
153
+            \OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
154
+            try {
155
+                self::requireAppFile($app);
156
+            } catch (Throwable $ex) {
157
+                if($ex instanceof ServerNotAvailableException) {
158
+                    throw $ex;
159
+                }
160
+                \OC::$server->getLogger()->logException($ex);
161
+
162
+                if (!\OC::$server->getAppManager()->isShipped($app) && !self::isType($app, ['authentication'])) {
163
+                    // Only disable apps which are not shipped and that are not authentication apps
164
+                    \OC::$server->getAppManager()->disableApp($app, true);
165
+                }
166
+            }
167
+            \OC::$server->getEventLogger()->end('load_app_' . $app);
168
+        }
169
+
170
+        $info = self::getAppInfo($app);
171
+        if (!empty($info['activity']['filters'])) {
172
+            foreach ($info['activity']['filters'] as $filter) {
173
+                \OC::$server->getActivityManager()->registerFilter($filter);
174
+            }
175
+        }
176
+        if (!empty($info['activity']['settings'])) {
177
+            foreach ($info['activity']['settings'] as $setting) {
178
+                \OC::$server->getActivityManager()->registerSetting($setting);
179
+            }
180
+        }
181
+        if (!empty($info['activity']['providers'])) {
182
+            foreach ($info['activity']['providers'] as $provider) {
183
+                \OC::$server->getActivityManager()->registerProvider($provider);
184
+            }
185
+        }
186
+
187
+        if (!empty($info['settings']['admin'])) {
188
+            foreach ($info['settings']['admin'] as $setting) {
189
+                \OC::$server->getSettingsManager()->registerSetting('admin', $setting);
190
+            }
191
+        }
192
+        if (!empty($info['settings']['admin-section'])) {
193
+            foreach ($info['settings']['admin-section'] as $section) {
194
+                \OC::$server->getSettingsManager()->registerSection('admin', $section);
195
+            }
196
+        }
197
+        if (!empty($info['settings']['personal'])) {
198
+            foreach ($info['settings']['personal'] as $setting) {
199
+                \OC::$server->getSettingsManager()->registerSetting('personal', $setting);
200
+            }
201
+        }
202
+        if (!empty($info['settings']['personal-section'])) {
203
+            foreach ($info['settings']['personal-section'] as $section) {
204
+                \OC::$server->getSettingsManager()->registerSection('personal', $section);
205
+            }
206
+        }
207
+
208
+        if (!empty($info['collaboration']['plugins'])) {
209
+            // deal with one or many plugin entries
210
+            $plugins = isset($info['collaboration']['plugins']['plugin']['@value']) ?
211
+                [$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin'];
212
+            foreach ($plugins as $plugin) {
213
+                if($plugin['@attributes']['type'] === 'collaborator-search') {
214
+                    $pluginInfo = [
215
+                        'shareType' => $plugin['@attributes']['share-type'],
216
+                        'class' => $plugin['@value'],
217
+                    ];
218
+                    \OC::$server->getCollaboratorSearch()->registerPlugin($pluginInfo);
219
+                } else if ($plugin['@attributes']['type'] === 'autocomplete-sort') {
220
+                    \OC::$server->getAutoCompleteManager()->registerSorter($plugin['@value']);
221
+                }
222
+            }
223
+        }
224
+    }
225
+
226
+    /**
227
+     * @internal
228
+     * @param string $app
229
+     * @param string $path
230
+     * @param bool $force
231
+     */
232
+    public static function registerAutoloading(string $app, string $path, bool $force = false) {
233
+        $key = $app . '-' . $path;
234
+        if (!$force && isset(self::$alreadyRegistered[$key])) {
235
+            return;
236
+        }
237
+
238
+        self::$alreadyRegistered[$key] = true;
239
+
240
+        // Register on PSR-4 composer autoloader
241
+        $appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
242
+        \OC::$server->registerNamespace($app, $appNamespace);
243
+
244
+        if (file_exists($path . '/composer/autoload.php')) {
245
+            require_once $path . '/composer/autoload.php';
246
+        } else {
247
+            \OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
248
+            // Register on legacy autoloader
249
+            \OC::$loader->addValidRoot($path);
250
+        }
251
+
252
+        // Register Test namespace only when testing
253
+        if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
254
+            \OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);
255
+        }
256
+    }
257
+
258
+    /**
259
+     * Load app.php from the given app
260
+     *
261
+     * @param string $app app name
262
+     * @throws Error
263
+     */
264
+    private static function requireAppFile(string $app) {
265
+        // encapsulated here to avoid variable scope conflicts
266
+        require_once $app . '/appinfo/app.php';
267
+    }
268
+
269
+    /**
270
+     * check if an app is of a specific type
271
+     *
272
+     * @param string $app
273
+     * @param array $types
274
+     * @return bool
275
+     */
276
+    public static function isType(string $app, array $types): bool {
277
+        $appTypes = self::getAppTypes($app);
278
+        foreach ($types as $type) {
279
+            if (array_search($type, $appTypes) !== false) {
280
+                return true;
281
+            }
282
+        }
283
+        return false;
284
+    }
285
+
286
+    /**
287
+     * get the types of an app
288
+     *
289
+     * @param string $app
290
+     * @return array
291
+     */
292
+    private static function getAppTypes(string $app): array {
293
+        //load the cache
294
+        if (count(self::$appTypes) == 0) {
295
+            self::$appTypes = \OC::$server->getAppConfig()->getValues(false, 'types');
296
+        }
297
+
298
+        if (isset(self::$appTypes[$app])) {
299
+            return explode(',', self::$appTypes[$app]);
300
+        }
301
+
302
+        return [];
303
+    }
304
+
305
+    /**
306
+     * read app types from info.xml and cache them in the database
307
+     */
308
+    public static function setAppTypes(string $app) {
309
+        $appManager = \OC::$server->getAppManager();
310
+        $appData = $appManager->getAppInfo($app);
311
+        if(!is_array($appData)) {
312
+            return;
313
+        }
314
+
315
+        if (isset($appData['types'])) {
316
+            $appTypes = implode(',', $appData['types']);
317
+        } else {
318
+            $appTypes = '';
319
+            $appData['types'] = [];
320
+        }
321
+
322
+        $config = \OC::$server->getConfig();
323
+        $config->setAppValue($app, 'types', $appTypes);
324
+
325
+        if ($appManager->hasProtectedAppType($appData['types'])) {
326
+            $enabled = $config->getAppValue($app, 'enabled', 'yes');
327
+            if ($enabled !== 'yes' && $enabled !== 'no') {
328
+                $config->setAppValue($app, 'enabled', 'yes');
329
+            }
330
+        }
331
+    }
332
+
333
+    /**
334
+     * Returns apps enabled for the current user.
335
+     *
336
+     * @param bool $forceRefresh whether to refresh the cache
337
+     * @param bool $all whether to return apps for all users, not only the
338
+     * currently logged in one
339
+     * @return string[]
340
+     */
341
+    public static function getEnabledApps(bool $forceRefresh = false, bool $all = false): array {
342
+        if (!\OC::$server->getSystemConfig()->getValue('installed', false)) {
343
+            return [];
344
+        }
345
+        // in incognito mode or when logged out, $user will be false,
346
+        // which is also the case during an upgrade
347
+        $appManager = \OC::$server->getAppManager();
348
+        if ($all) {
349
+            $user = null;
350
+        } else {
351
+            $user = \OC::$server->getUserSession()->getUser();
352
+        }
353
+
354
+        if (is_null($user)) {
355
+            $apps = $appManager->getInstalledApps();
356
+        } else {
357
+            $apps = $appManager->getEnabledAppsForUser($user);
358
+        }
359
+        $apps = array_filter($apps, function ($app) {
360
+            return $app !== 'files';//we add this manually
361
+        });
362
+        sort($apps);
363
+        array_unshift($apps, 'files');
364
+        return $apps;
365
+    }
366
+
367
+    /**
368
+     * checks whether or not an app is enabled
369
+     *
370
+     * @param string $app app
371
+     * @return bool
372
+     * @deprecated 13.0.0 use \OC::$server->getAppManager()->isEnabledForUser($appId)
373
+     *
374
+     * This function checks whether or not an app is enabled.
375
+     */
376
+    public static function isEnabled(string $app): bool {
377
+        return \OC::$server->getAppManager()->isEnabledForUser($app);
378
+    }
379
+
380
+    /**
381
+     * enables an app
382
+     *
383
+     * @param string $appId
384
+     * @param array $groups (optional) when set, only these groups will have access to the app
385
+     * @throws \Exception
386
+     * @return void
387
+     *
388
+     * This function set an app as enabled in appconfig.
389
+     */
390
+    public function enable(string $appId,
391
+                            array $groups = []) {
392
+
393
+        // Check if app is already downloaded
394
+        /** @var Installer $installer */
395
+        $installer = \OC::$server->query(Installer::class);
396
+        $isDownloaded = $installer->isDownloaded($appId);
397
+
398
+        if(!$isDownloaded) {
399
+            $installer->downloadApp($appId);
400
+        }
401
+
402
+        $installer->installApp($appId);
403
+
404
+        $appManager = \OC::$server->getAppManager();
405
+        if ($groups !== []) {
406
+            $groupManager = \OC::$server->getGroupManager();
407
+            $groupsList = [];
408
+            foreach ($groups as $group) {
409
+                $groupItem = $groupManager->get($group);
410
+                if ($groupItem instanceof \OCP\IGroup) {
411
+                    $groupsList[] = $groupManager->get($group);
412
+                }
413
+            }
414
+            $appManager->enableAppForGroups($appId, $groupsList);
415
+        } else {
416
+            $appManager->enableApp($appId);
417
+        }
418
+    }
419
+
420
+    /**
421
+     * Get the path where to install apps
422
+     *
423
+     * @return string|false
424
+     */
425
+    public static function getInstallPath() {
426
+        if (\OC::$server->getSystemConfig()->getValue('appstoreenabled', true) == false) {
427
+            return false;
428
+        }
429
+
430
+        foreach (OC::$APPSROOTS as $dir) {
431
+            if (isset($dir['writable']) && $dir['writable'] === true) {
432
+                return $dir['path'];
433
+            }
434
+        }
435
+
436
+        \OCP\Util::writeLog('core', 'No application directories are marked as writable.', ILogger::ERROR);
437
+        return null;
438
+    }
439
+
440
+
441
+    /**
442
+     * search for an app in all app-directories
443
+     *
444
+     * @param string $appId
445
+     * @return false|string
446
+     */
447
+    public static function findAppInDirectories(string $appId) {
448
+        $sanitizedAppId = self::cleanAppId($appId);
449
+        if($sanitizedAppId !== $appId) {
450
+            return false;
451
+        }
452
+        static $app_dir = [];
453
+
454
+        if (isset($app_dir[$appId])) {
455
+            return $app_dir[$appId];
456
+        }
457
+
458
+        $possibleApps = [];
459
+        foreach (OC::$APPSROOTS as $dir) {
460
+            if (file_exists($dir['path'] . '/' . $appId)) {
461
+                $possibleApps[] = $dir;
462
+            }
463
+        }
464
+
465
+        if (empty($possibleApps)) {
466
+            return false;
467
+        } elseif (count($possibleApps) === 1) {
468
+            $dir = array_shift($possibleApps);
469
+            $app_dir[$appId] = $dir;
470
+            return $dir;
471
+        } else {
472
+            $versionToLoad = [];
473
+            foreach ($possibleApps as $possibleApp) {
474
+                $version = self::getAppVersionByPath($possibleApp['path'] . '/' . $appId);
475
+                if (empty($versionToLoad) || version_compare($version, $versionToLoad['version'], '>')) {
476
+                    $versionToLoad = [
477
+                        'dir' => $possibleApp,
478
+                        'version' => $version,
479
+                    ];
480
+                }
481
+            }
482
+            $app_dir[$appId] = $versionToLoad['dir'];
483
+            return $versionToLoad['dir'];
484
+            //TODO - write test
485
+        }
486
+    }
487
+
488
+    /**
489
+     * Get the directory for the given app.
490
+     * If the app is defined in multiple directories, the first one is taken. (false if not found)
491
+     *
492
+     * @param string $appId
493
+     * @return string|false
494
+     * @deprecated 11.0.0 use \OC::$server->getAppManager()->getAppPath()
495
+     */
496
+    public static function getAppPath(string $appId) {
497
+        if ($appId === null || trim($appId) === '') {
498
+            return false;
499
+        }
500
+
501
+        if (($dir = self::findAppInDirectories($appId)) != false) {
502
+            return $dir['path'] . '/' . $appId;
503
+        }
504
+        return false;
505
+    }
506
+
507
+    /**
508
+     * Get the path for the given app on the access
509
+     * If the app is defined in multiple directories, the first one is taken. (false if not found)
510
+     *
511
+     * @param string $appId
512
+     * @return string|false
513
+     * @deprecated 18.0.0 use \OC::$server->getAppManager()->getAppWebPath()
514
+     */
515
+    public static function getAppWebPath(string $appId) {
516
+        if (($dir = self::findAppInDirectories($appId)) != false) {
517
+            return OC::$WEBROOT . $dir['url'] . '/' . $appId;
518
+        }
519
+        return false;
520
+    }
521
+
522
+    /**
523
+     * get the last version of the app from appinfo/info.xml
524
+     *
525
+     * @param string $appId
526
+     * @param bool $useCache
527
+     * @return string
528
+     * @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppVersion()
529
+     */
530
+    public static function getAppVersion(string $appId, bool $useCache = true): string {
531
+        return \OC::$server->getAppManager()->getAppVersion($appId, $useCache);
532
+    }
533
+
534
+    /**
535
+     * get app's version based on it's path
536
+     *
537
+     * @param string $path
538
+     * @return string
539
+     */
540
+    public static function getAppVersionByPath(string $path): string {
541
+        $infoFile = $path . '/appinfo/info.xml';
542
+        $appData = \OC::$server->getAppManager()->getAppInfo($infoFile, true);
543
+        return isset($appData['version']) ? $appData['version'] : '';
544
+    }
545
+
546
+
547
+    /**
548
+     * Read all app metadata from the info.xml file
549
+     *
550
+     * @param string $appId id of the app or the path of the info.xml file
551
+     * @param bool $path
552
+     * @param string $lang
553
+     * @return array|null
554
+     * @note all data is read from info.xml, not just pre-defined fields
555
+     * @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppInfo()
556
+     */
557
+    public static function getAppInfo(string $appId, bool $path = false, string $lang = null) {
558
+        return \OC::$server->getAppManager()->getAppInfo($appId, $path, $lang);
559
+    }
560
+
561
+    /**
562
+     * Returns the navigation
563
+     *
564
+     * @return array
565
+     * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll()
566
+     *
567
+     * This function returns an array containing all entries added. The
568
+     * entries are sorted by the key 'order' ascending. Additional to the keys
569
+     * given for each app the following keys exist:
570
+     *   - active: boolean, signals if the user is on this navigation entry
571
+     */
572
+    public static function getNavigation(): array {
573
+        return OC::$server->getNavigationManager()->getAll();
574
+    }
575
+
576
+    /**
577
+     * Returns the Settings Navigation
578
+     *
579
+     * @return string[]
580
+     * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll('settings')
581
+     *
582
+     * This function returns an array containing all settings pages added. The
583
+     * entries are sorted by the key 'order' ascending.
584
+     */
585
+    public static function getSettingsNavigation(): array {
586
+        return OC::$server->getNavigationManager()->getAll('settings');
587
+    }
588
+
589
+    /**
590
+     * get the id of loaded app
591
+     *
592
+     * @return string
593
+     */
594
+    public static function getCurrentApp(): string {
595
+        $request = \OC::$server->getRequest();
596
+        $script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1);
597
+        $topFolder = substr($script, 0, strpos($script, '/') ?: 0);
598
+        if (empty($topFolder)) {
599
+            $path_info = $request->getPathInfo();
600
+            if ($path_info) {
601
+                $topFolder = substr($path_info, 1, strpos($path_info, '/', 1) - 1);
602
+            }
603
+        }
604
+        if ($topFolder == 'apps') {
605
+            $length = strlen($topFolder);
606
+            return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1) ?: '';
607
+        } else {
608
+            return $topFolder;
609
+        }
610
+    }
611
+
612
+    /**
613
+     * @param string $type
614
+     * @return array
615
+     */
616
+    public static function getForms(string $type): array {
617
+        $forms = [];
618
+        switch ($type) {
619
+            case 'admin':
620
+                $source = self::$adminForms;
621
+                break;
622
+            case 'personal':
623
+                $source = self::$personalForms;
624
+                break;
625
+            default:
626
+                return [];
627
+        }
628
+        foreach ($source as $form) {
629
+            $forms[] = include $form;
630
+        }
631
+        return $forms;
632
+    }
633
+
634
+    /**
635
+     * register an admin form to be shown
636
+     *
637
+     * @param string $app
638
+     * @param string $page
639
+     */
640
+    public static function registerAdmin(string $app, string $page) {
641
+        self::$adminForms[] = $app . '/' . $page . '.php';
642
+    }
643
+
644
+    /**
645
+     * register a personal form to be shown
646
+     * @param string $app
647
+     * @param string $page
648
+     */
649
+    public static function registerPersonal(string $app, string $page) {
650
+        self::$personalForms[] = $app . '/' . $page . '.php';
651
+    }
652
+
653
+    /**
654
+     * @param array $entry
655
+     */
656
+    public static function registerLogIn(array $entry) {
657
+        self::$altLogin[] = $entry;
658
+    }
659
+
660
+    /**
661
+     * @return array
662
+     */
663
+    public static function getAlternativeLogIns(): array {
664
+        return self::$altLogin;
665
+    }
666
+
667
+    /**
668
+     * get a list of all apps in the apps folder
669
+     *
670
+     * @return array an array of app names (string IDs)
671
+     * @todo: change the name of this method to getInstalledApps, which is more accurate
672
+     */
673
+    public static function getAllApps(): array {
674
+
675
+        $apps = [];
676
+
677
+        foreach (OC::$APPSROOTS as $apps_dir) {
678
+            if (!is_readable($apps_dir['path'])) {
679
+                \OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], ILogger::WARN);
680
+                continue;
681
+            }
682
+            $dh = opendir($apps_dir['path']);
683
+
684
+            if (is_resource($dh)) {
685
+                while (($file = readdir($dh)) !== false) {
686
+
687
+                    if ($file[0] != '.' and is_dir($apps_dir['path'] . '/' . $file) and is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml')) {
688
+
689
+                        $apps[] = $file;
690
+                    }
691
+                }
692
+            }
693
+        }
694
+
695
+        $apps = array_unique($apps);
696
+
697
+        return $apps;
698
+    }
699
+
700
+    /**
701
+     * List all apps, this is used in apps.php
702
+     *
703
+     * @return array
704
+     */
705
+    public function listAllApps(): array {
706
+        $installedApps = OC_App::getAllApps();
707
+
708
+        $appManager = \OC::$server->getAppManager();
709
+        //we don't want to show configuration for these
710
+        $blacklist = $appManager->getAlwaysEnabledApps();
711
+        $appList = [];
712
+        $langCode = \OC::$server->getL10N('core')->getLanguageCode();
713
+        $urlGenerator = \OC::$server->getURLGenerator();
714
+        /** @var \OCP\Support\Subscription\IRegistry $subscriptionRegistry */
715
+        $subscriptionRegistry = \OC::$server->query(\OCP\Support\Subscription\IRegistry::class);
716
+        $supportedApps = $subscriptionRegistry->delegateGetSupportedApps();
717
+
718
+        foreach ($installedApps as $app) {
719
+            if (array_search($app, $blacklist) === false) {
720
+
721
+                $info = OC_App::getAppInfo($app, false, $langCode);
722
+                if (!is_array($info)) {
723
+                    \OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', ILogger::ERROR);
724
+                    continue;
725
+                }
726
+
727
+                if (!isset($info['name'])) {
728
+                    \OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', ILogger::ERROR);
729
+                    continue;
730
+                }
731
+
732
+                $enabled = \OC::$server->getConfig()->getAppValue($app, 'enabled', 'no');
733
+                $info['groups'] = null;
734
+                if ($enabled === 'yes') {
735
+                    $active = true;
736
+                } else if ($enabled === 'no') {
737
+                    $active = false;
738
+                } else {
739
+                    $active = true;
740
+                    $info['groups'] = $enabled;
741
+                }
742
+
743
+                $info['active'] = $active;
744
+
745
+                if ($appManager->isShipped($app)) {
746
+                    $info['internal'] = true;
747
+                    $info['level'] = self::officialApp;
748
+                    $info['removable'] = false;
749
+                } else {
750
+                    $info['internal'] = false;
751
+                    $info['removable'] = true;
752
+                }
753
+
754
+                if (in_array($app, $supportedApps)) {
755
+                    $info['level'] = self::supportedApp;
756
+                }
757
+
758
+                $appPath = self::getAppPath($app);
759
+                if($appPath !== false) {
760
+                    $appIcon = $appPath . '/img/' . $app . '.svg';
761
+                    if (file_exists($appIcon)) {
762
+                        $info['preview'] = $urlGenerator->imagePath($app, $app . '.svg');
763
+                        $info['previewAsIcon'] = true;
764
+                    } else {
765
+                        $appIcon = $appPath . '/img/app.svg';
766
+                        if (file_exists($appIcon)) {
767
+                            $info['preview'] = $urlGenerator->imagePath($app, 'app.svg');
768
+                            $info['previewAsIcon'] = true;
769
+                        }
770
+                    }
771
+                }
772
+                // fix documentation
773
+                if (isset($info['documentation']) && is_array($info['documentation'])) {
774
+                    foreach ($info['documentation'] as $key => $url) {
775
+                        // If it is not an absolute URL we assume it is a key
776
+                        // i.e. admin-ldap will get converted to go.php?to=admin-ldap
777
+                        if (stripos($url, 'https://') !== 0 && stripos($url, 'http://') !== 0) {
778
+                            $url = $urlGenerator->linkToDocs($url);
779
+                        }
780
+
781
+                        $info['documentation'][$key] = $url;
782
+                    }
783
+                }
784
+
785
+                $info['version'] = OC_App::getAppVersion($app);
786
+                $appList[] = $info;
787
+            }
788
+        }
789
+
790
+        return $appList;
791
+    }
792
+
793
+    public static function shouldUpgrade(string $app): bool {
794
+        $versions = self::getAppVersions();
795
+        $currentVersion = OC_App::getAppVersion($app);
796
+        if ($currentVersion && isset($versions[$app])) {
797
+            $installedVersion = $versions[$app];
798
+            if (!version_compare($currentVersion, $installedVersion, '=')) {
799
+                return true;
800
+            }
801
+        }
802
+        return false;
803
+    }
804
+
805
+    /**
806
+     * Adjust the number of version parts of $version1 to match
807
+     * the number of version parts of $version2.
808
+     *
809
+     * @param string $version1 version to adjust
810
+     * @param string $version2 version to take the number of parts from
811
+     * @return string shortened $version1
812
+     */
813
+    private static function adjustVersionParts(string $version1, string $version2): string {
814
+        $version1 = explode('.', $version1);
815
+        $version2 = explode('.', $version2);
816
+        // reduce $version1 to match the number of parts in $version2
817
+        while (count($version1) > count($version2)) {
818
+            array_pop($version1);
819
+        }
820
+        // if $version1 does not have enough parts, add some
821
+        while (count($version1) < count($version2)) {
822
+            $version1[] = '0';
823
+        }
824
+        return implode('.', $version1);
825
+    }
826
+
827
+    /**
828
+     * Check whether the current ownCloud version matches the given
829
+     * application's version requirements.
830
+     *
831
+     * The comparison is made based on the number of parts that the
832
+     * app info version has. For example for ownCloud 6.0.3 if the
833
+     * app info version is expecting version 6.0, the comparison is
834
+     * made on the first two parts of the ownCloud version.
835
+     * This means that it's possible to specify "requiremin" => 6
836
+     * and "requiremax" => 6 and it will still match ownCloud 6.0.3.
837
+     *
838
+     * @param string $ocVersion ownCloud version to check against
839
+     * @param array $appInfo app info (from xml)
840
+     *
841
+     * @return boolean true if compatible, otherwise false
842
+     */
843
+    public static function isAppCompatible(string $ocVersion, array $appInfo, bool $ignoreMax = false): bool {
844
+        $requireMin = '';
845
+        $requireMax = '';
846
+        if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) {
847
+            $requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version'];
848
+        } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) {
849
+            $requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version'];
850
+        } else if (isset($appInfo['requiremin'])) {
851
+            $requireMin = $appInfo['requiremin'];
852
+        } else if (isset($appInfo['require'])) {
853
+            $requireMin = $appInfo['require'];
854
+        }
855
+
856
+        if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) {
857
+            $requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version'];
858
+        } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) {
859
+            $requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version'];
860
+        } else if (isset($appInfo['requiremax'])) {
861
+            $requireMax = $appInfo['requiremax'];
862
+        }
863
+
864
+        if (!empty($requireMin)
865
+            && version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<')
866
+        ) {
867
+
868
+            return false;
869
+        }
870
+
871
+        if (!$ignoreMax && !empty($requireMax)
872
+            && version_compare(self::adjustVersionParts($ocVersion, $requireMax), $requireMax, '>')
873
+        ) {
874
+            return false;
875
+        }
876
+
877
+        return true;
878
+    }
879
+
880
+    /**
881
+     * get the installed version of all apps
882
+     */
883
+    public static function getAppVersions() {
884
+        static $versions;
885
+
886
+        if(!$versions) {
887
+            $appConfig = \OC::$server->getAppConfig();
888
+            $versions = $appConfig->getValues(false, 'installed_version');
889
+        }
890
+        return $versions;
891
+    }
892
+
893
+    /**
894
+     * update the database for the app and call the update script
895
+     *
896
+     * @param string $appId
897
+     * @return bool
898
+     */
899
+    public static function updateApp(string $appId): bool {
900
+        $appPath = self::getAppPath($appId);
901
+        if($appPath === false) {
902
+            return false;
903
+        }
904
+
905
+        \OC::$server->getAppManager()->clearAppsCache();
906
+        $appData = self::getAppInfo($appId);
907
+
908
+        self::registerAutoloading($appId, $appPath, true);
909
+        self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
910
+
911
+        if (file_exists($appPath . '/appinfo/database.xml')) {
912
+            OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
913
+        } else {
914
+            $ms = new MigrationService($appId, \OC::$server->getDatabaseConnection());
915
+            $ms->migrate();
916
+        }
917
+
918
+        self::executeRepairSteps($appId, $appData['repair-steps']['post-migration']);
919
+        self::setupLiveMigrations($appId, $appData['repair-steps']['live-migration']);
920
+        // update appversion in app manager
921
+        \OC::$server->getAppManager()->clearAppsCache();
922
+        \OC::$server->getAppManager()->getAppVersion($appId, false);
923
+
924
+        // run upgrade code
925
+        if (file_exists($appPath . '/appinfo/update.php')) {
926
+            self::loadApp($appId);
927
+            include $appPath . '/appinfo/update.php';
928
+        }
929
+        self::setupBackgroundJobs($appData['background-jobs']);
930
+
931
+        //set remote/public handlers
932
+        if (array_key_exists('ocsid', $appData)) {
933
+            \OC::$server->getConfig()->setAppValue($appId, 'ocsid', $appData['ocsid']);
934
+        } elseif(\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
935
+            \OC::$server->getConfig()->deleteAppValue($appId, 'ocsid');
936
+        }
937
+        foreach ($appData['remote'] as $name => $path) {
938
+            \OC::$server->getConfig()->setAppValue('core', 'remote_' . $name, $appId . '/' . $path);
939
+        }
940
+        foreach ($appData['public'] as $name => $path) {
941
+            \OC::$server->getConfig()->setAppValue('core', 'public_' . $name, $appId . '/' . $path);
942
+        }
943
+
944
+        self::setAppTypes($appId);
945
+
946
+        $version = \OC_App::getAppVersion($appId);
947
+        \OC::$server->getConfig()->setAppValue($appId, 'installed_version', $version);
948
+
949
+        \OC::$server->getEventDispatcher()->dispatch(ManagerEvent::EVENT_APP_UPDATE, new ManagerEvent(
950
+            ManagerEvent::EVENT_APP_UPDATE, $appId
951
+        ));
952
+
953
+        return true;
954
+    }
955
+
956
+    /**
957
+     * @param string $appId
958
+     * @param string[] $steps
959
+     * @throws \OC\NeedsUpdateException
960
+     */
961
+    public static function executeRepairSteps(string $appId, array $steps) {
962
+        if (empty($steps)) {
963
+            return;
964
+        }
965
+        // load the app
966
+        self::loadApp($appId);
967
+
968
+        $dispatcher = OC::$server->getEventDispatcher();
969
+
970
+        // load the steps
971
+        $r = new Repair([], $dispatcher);
972
+        foreach ($steps as $step) {
973
+            try {
974
+                $r->addStep($step);
975
+            } catch (Exception $ex) {
976
+                $r->emit('\OC\Repair', 'error', [$ex->getMessage()]);
977
+                \OC::$server->getLogger()->logException($ex);
978
+            }
979
+        }
980
+        // run the steps
981
+        $r->run();
982
+    }
983
+
984
+    public static function setupBackgroundJobs(array $jobs) {
985
+        $queue = \OC::$server->getJobList();
986
+        foreach ($jobs as $job) {
987
+            $queue->add($job);
988
+        }
989
+    }
990
+
991
+    /**
992
+     * @param string $appId
993
+     * @param string[] $steps
994
+     */
995
+    private static function setupLiveMigrations(string $appId, array $steps) {
996
+        $queue = \OC::$server->getJobList();
997
+        foreach ($steps as $step) {
998
+            $queue->add('OC\Migration\BackgroundRepair', [
999
+                'app' => $appId,
1000
+                'step' => $step]);
1001
+        }
1002
+    }
1003
+
1004
+    /**
1005
+     * @param string $appId
1006
+     * @return \OC\Files\View|false
1007
+     */
1008
+    public static function getStorage(string $appId) {
1009
+        if (\OC::$server->getAppManager()->isEnabledForUser($appId)) { //sanity check
1010
+            if (\OC::$server->getUserSession()->isLoggedIn()) {
1011
+                $view = new \OC\Files\View('/' . OC_User::getUser());
1012
+                if (!$view->file_exists($appId)) {
1013
+                    $view->mkdir($appId);
1014
+                }
1015
+                return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
1016
+            } else {
1017
+                \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', ILogger::ERROR);
1018
+                return false;
1019
+            }
1020
+        } else {
1021
+            \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', ILogger::ERROR);
1022
+            return false;
1023
+        }
1024
+    }
1025
+
1026
+    protected static function findBestL10NOption(array $options, string $lang): string {
1027
+        // only a single option
1028
+        if (isset($options['@value'])) {
1029
+            return $options['@value'];
1030
+        }
1031
+
1032
+        $fallback = $similarLangFallback = $englishFallback = false;
1033
+
1034
+        $lang = strtolower($lang);
1035
+        $similarLang = $lang;
1036
+        if (strpos($similarLang, '_')) {
1037
+            // For "de_DE" we want to find "de" and the other way around
1038
+            $similarLang = substr($lang, 0, strpos($lang, '_'));
1039
+        }
1040
+
1041
+        foreach ($options as $option) {
1042
+            if (is_array($option)) {
1043
+                if ($fallback === false) {
1044
+                    $fallback = $option['@value'];
1045
+                }
1046
+
1047
+                if (!isset($option['@attributes']['lang'])) {
1048
+                    continue;
1049
+                }
1050
+
1051
+                $attributeLang = strtolower($option['@attributes']['lang']);
1052
+                if ($attributeLang === $lang) {
1053
+                    return $option['@value'];
1054
+                }
1055
+
1056
+                if ($attributeLang === $similarLang) {
1057
+                    $similarLangFallback = $option['@value'];
1058
+                } else if (strpos($attributeLang, $similarLang . '_') === 0) {
1059
+                    if ($similarLangFallback === false) {
1060
+                        $similarLangFallback =  $option['@value'];
1061
+                    }
1062
+                }
1063
+            } else {
1064
+                $englishFallback = $option;
1065
+            }
1066
+        }
1067
+
1068
+        if ($similarLangFallback !== false) {
1069
+            return $similarLangFallback;
1070
+        } else if ($englishFallback !== false) {
1071
+            return $englishFallback;
1072
+        }
1073
+        return (string) $fallback;
1074
+    }
1075
+
1076
+    /**
1077
+     * parses the app data array and enhanced the 'description' value
1078
+     *
1079
+     * @param array $data the app data
1080
+     * @param string $lang
1081
+     * @return array improved app data
1082
+     */
1083
+    public static function parseAppInfo(array $data, $lang = null): array {
1084
+
1085
+        if ($lang && isset($data['name']) && is_array($data['name'])) {
1086
+            $data['name'] = self::findBestL10NOption($data['name'], $lang);
1087
+        }
1088
+        if ($lang && isset($data['summary']) && is_array($data['summary'])) {
1089
+            $data['summary'] = self::findBestL10NOption($data['summary'], $lang);
1090
+        }
1091
+        if ($lang && isset($data['description']) && is_array($data['description'])) {
1092
+            $data['description'] = trim(self::findBestL10NOption($data['description'], $lang));
1093
+        } else if (isset($data['description']) && is_string($data['description'])) {
1094
+            $data['description'] = trim($data['description']);
1095
+        } else  {
1096
+            $data['description'] = '';
1097
+        }
1098
+
1099
+        return $data;
1100
+    }
1101
+
1102
+    /**
1103
+     * @param \OCP\IConfig $config
1104
+     * @param \OCP\IL10N $l
1105
+     * @param array $info
1106
+     * @throws \Exception
1107
+     */
1108
+    public static function checkAppDependencies(\OCP\IConfig $config, \OCP\IL10N $l, array $info, bool $ignoreMax) {
1109
+        $dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
1110
+        $missing = $dependencyAnalyzer->analyze($info, $ignoreMax);
1111
+        if (!empty($missing)) {
1112
+            $missingMsg = implode(PHP_EOL, $missing);
1113
+            throw new \Exception(
1114
+                $l->t('App "%1$s" cannot be installed because the following dependencies are not fulfilled: %2$s',
1115
+                    [$info['name'], $missingMsg]
1116
+                )
1117
+            );
1118
+        }
1119
+    }
1120 1120
 }
Please login to merge, or discard this patch.
lib/private/legacy/hook.php 1 patch
Indentation   +103 added lines, -103 removed lines patch added patch discarded remove patch
@@ -34,118 +34,118 @@
 block discarded – undo
34 34
  * @deprecated 18.0.0 use events and the \OCP\EventDispatcher\IEventDispatcher service
35 35
  */
36 36
 class OC_Hook {
37
-	public static $thrownExceptions = [];
37
+    public static $thrownExceptions = [];
38 38
 
39
-	static private $registered = [];
39
+    static private $registered = [];
40 40
 
41
-	/**
42
-	 * connects a function to a hook
43
-	 *
44
-	 * @param string $signalClass class name of emitter
45
-	 * @param string $signalName name of signal
46
-	 * @param string|object $slotClass class name of slot
47
-	 * @param string $slotName name of slot
48
-	 * @return bool
49
-	 *
50
-	 * This function makes it very easy to connect to use hooks.
51
-	 *
52
-	 * TODO: write example
53
-	 */
54
-	static public function connect($signalClass, $signalName, $slotClass, $slotName ) {
55
-		// If we're trying to connect to an emitting class that isn't
56
-		// yet registered, register it
57
-		if( !array_key_exists($signalClass, self::$registered )) {
58
-			self::$registered[$signalClass] = [];
59
-		}
60
-		// If we're trying to connect to an emitting method that isn't
61
-		// yet registered, register it with the emitting class
62
-		if( !array_key_exists( $signalName, self::$registered[$signalClass] )) {
63
-			self::$registered[$signalClass][$signalName] = [];
64
-		}
41
+    /**
42
+     * connects a function to a hook
43
+     *
44
+     * @param string $signalClass class name of emitter
45
+     * @param string $signalName name of signal
46
+     * @param string|object $slotClass class name of slot
47
+     * @param string $slotName name of slot
48
+     * @return bool
49
+     *
50
+     * This function makes it very easy to connect to use hooks.
51
+     *
52
+     * TODO: write example
53
+     */
54
+    static public function connect($signalClass, $signalName, $slotClass, $slotName ) {
55
+        // If we're trying to connect to an emitting class that isn't
56
+        // yet registered, register it
57
+        if( !array_key_exists($signalClass, self::$registered )) {
58
+            self::$registered[$signalClass] = [];
59
+        }
60
+        // If we're trying to connect to an emitting method that isn't
61
+        // yet registered, register it with the emitting class
62
+        if( !array_key_exists( $signalName, self::$registered[$signalClass] )) {
63
+            self::$registered[$signalClass][$signalName] = [];
64
+        }
65 65
 
66
-		// don't connect hooks twice
67
-		foreach (self::$registered[$signalClass][$signalName] as $hook) {
68
-			if ($hook['class'] === $slotClass and $hook['name'] === $slotName) {
69
-				return false;
70
-			}
71
-		}
72
-		// Connect the hook handler to the requested emitter
73
-		self::$registered[$signalClass][$signalName][] = [
74
-				"class" => $slotClass,
75
-				"name" => $slotName
76
-		];
66
+        // don't connect hooks twice
67
+        foreach (self::$registered[$signalClass][$signalName] as $hook) {
68
+            if ($hook['class'] === $slotClass and $hook['name'] === $slotName) {
69
+                return false;
70
+            }
71
+        }
72
+        // Connect the hook handler to the requested emitter
73
+        self::$registered[$signalClass][$signalName][] = [
74
+                "class" => $slotClass,
75
+                "name" => $slotName
76
+        ];
77 77
 
78
-		// No chance for failure ;-)
79
-		return true;
80
-	}
78
+        // No chance for failure ;-)
79
+        return true;
80
+    }
81 81
 
82
-	/**
83
-	 * emits a signal
84
-	 *
85
-	 * @param string $signalClass class name of emitter
86
-	 * @param string $signalName name of signal
87
-	 * @param mixed $params default: array() array with additional data
88
-	 * @return bool true if slots exists or false if not
89
-	 * @throws \OC\HintException
90
-	 * @throws \OC\ServerNotAvailableException Emits a signal. To get data from the slot use references!
91
-	 *
92
-	 * TODO: write example
93
-	 */
94
-	static public function emit($signalClass, $signalName, $params = []) {
82
+    /**
83
+     * emits a signal
84
+     *
85
+     * @param string $signalClass class name of emitter
86
+     * @param string $signalName name of signal
87
+     * @param mixed $params default: array() array with additional data
88
+     * @return bool true if slots exists or false if not
89
+     * @throws \OC\HintException
90
+     * @throws \OC\ServerNotAvailableException Emits a signal. To get data from the slot use references!
91
+     *
92
+     * TODO: write example
93
+     */
94
+    static public function emit($signalClass, $signalName, $params = []) {
95 95
 
96
-		// Return false if no hook handlers are listening to this
97
-		// emitting class
98
-		if( !array_key_exists($signalClass, self::$registered )) {
99
-			return false;
100
-		}
96
+        // Return false if no hook handlers are listening to this
97
+        // emitting class
98
+        if( !array_key_exists($signalClass, self::$registered )) {
99
+            return false;
100
+        }
101 101
 
102
-		// Return false if no hook handlers are listening to this
103
-		// emitting method
104
-		if( !array_key_exists( $signalName, self::$registered[$signalClass] )) {
105
-			return false;
106
-		}
102
+        // Return false if no hook handlers are listening to this
103
+        // emitting method
104
+        if( !array_key_exists( $signalName, self::$registered[$signalClass] )) {
105
+            return false;
106
+        }
107 107
 
108
-		// Call all slots
109
-		foreach( self::$registered[$signalClass][$signalName] as $i ) {
110
-			try {
111
-				call_user_func( [ $i["class"], $i["name"] ], $params );
112
-			} catch (Exception $e){
113
-				self::$thrownExceptions[] = $e;
114
-				\OC::$server->getLogger()->logException($e);
115
-				if($e instanceof \OC\HintException) {
116
-					throw $e;
117
-				}
118
-				if($e instanceof \OC\ServerNotAvailableException) {
119
-					throw $e;
120
-				}
121
-			}
122
-		}
108
+        // Call all slots
109
+        foreach( self::$registered[$signalClass][$signalName] as $i ) {
110
+            try {
111
+                call_user_func( [ $i["class"], $i["name"] ], $params );
112
+            } catch (Exception $e){
113
+                self::$thrownExceptions[] = $e;
114
+                \OC::$server->getLogger()->logException($e);
115
+                if($e instanceof \OC\HintException) {
116
+                    throw $e;
117
+                }
118
+                if($e instanceof \OC\ServerNotAvailableException) {
119
+                    throw $e;
120
+                }
121
+            }
122
+        }
123 123
 
124
-		return true;
125
-	}
124
+        return true;
125
+    }
126 126
 
127
-	/**
128
-	 * clear hooks
129
-	 * @param string $signalClass
130
-	 * @param string $signalName
131
-	 */
132
-	static public function clear($signalClass='', $signalName='') {
133
-		if ($signalClass) {
134
-			if ($signalName) {
135
-				self::$registered[$signalClass][$signalName]=[];
136
-			}else{
137
-				self::$registered[$signalClass]=[];
138
-			}
139
-		}else{
140
-			self::$registered=[];
141
-		}
142
-	}
127
+    /**
128
+     * clear hooks
129
+     * @param string $signalClass
130
+     * @param string $signalName
131
+     */
132
+    static public function clear($signalClass='', $signalName='') {
133
+        if ($signalClass) {
134
+            if ($signalName) {
135
+                self::$registered[$signalClass][$signalName]=[];
136
+            }else{
137
+                self::$registered[$signalClass]=[];
138
+            }
139
+        }else{
140
+            self::$registered=[];
141
+        }
142
+    }
143 143
 
144
-	/**
145
-	 * DO NOT USE!
146
-	 * For unit tests ONLY!
147
-	 */
148
-	static public function getHooks() {
149
-		return self::$registered;
150
-	}
144
+    /**
145
+     * DO NOT USE!
146
+     * For unit tests ONLY!
147
+     */
148
+    static public function getHooks() {
149
+        return self::$registered;
150
+    }
151 151
 }
Please login to merge, or discard this patch.
lib/private/legacy/helper.php 1 patch
Indentation   +553 added lines, -553 removed lines patch added patch discarded remove patch
@@ -48,557 +48,557 @@
 block discarded – undo
48 48
  * Collection of useful functions
49 49
  */
50 50
 class OC_Helper {
51
-	private static $templateManager;
52
-
53
-	/**
54
-	 * Make a human file size
55
-	 * @param int $bytes file size in bytes
56
-	 * @return string a human readable file size
57
-	 *
58
-	 * Makes 2048 to 2 kB.
59
-	 */
60
-	public static function humanFileSize($bytes) {
61
-		if ($bytes < 0) {
62
-			return "?";
63
-		}
64
-		if ($bytes < 1024) {
65
-			return "$bytes B";
66
-		}
67
-		$bytes = round($bytes / 1024, 0);
68
-		if ($bytes < 1024) {
69
-			return "$bytes KB";
70
-		}
71
-		$bytes = round($bytes / 1024, 1);
72
-		if ($bytes < 1024) {
73
-			return "$bytes MB";
74
-		}
75
-		$bytes = round($bytes / 1024, 1);
76
-		if ($bytes < 1024) {
77
-			return "$bytes GB";
78
-		}
79
-		$bytes = round($bytes / 1024, 1);
80
-		if ($bytes < 1024) {
81
-			return "$bytes TB";
82
-		}
83
-
84
-		$bytes = round($bytes / 1024, 1);
85
-		return "$bytes PB";
86
-	}
87
-
88
-	/**
89
-	 * Make a computer file size
90
-	 * @param string $str file size in human readable format
91
-	 * @return float|bool a file size in bytes
92
-	 *
93
-	 * Makes 2kB to 2048.
94
-	 *
95
-	 * Inspired by: http://www.php.net/manual/en/function.filesize.php#92418
96
-	 */
97
-	public static function computerFileSize($str) {
98
-		$str = strtolower($str);
99
-		if (is_numeric($str)) {
100
-			return (float)$str;
101
-		}
102
-
103
-		$bytes_array = [
104
-			'b' => 1,
105
-			'k' => 1024,
106
-			'kb' => 1024,
107
-			'mb' => 1024 * 1024,
108
-			'm' => 1024 * 1024,
109
-			'gb' => 1024 * 1024 * 1024,
110
-			'g' => 1024 * 1024 * 1024,
111
-			'tb' => 1024 * 1024 * 1024 * 1024,
112
-			't' => 1024 * 1024 * 1024 * 1024,
113
-			'pb' => 1024 * 1024 * 1024 * 1024 * 1024,
114
-			'p' => 1024 * 1024 * 1024 * 1024 * 1024,
115
-		];
116
-
117
-		$bytes = (float)$str;
118
-
119
-		if (preg_match('#([kmgtp]?b?)$#si', $str, $matches) && !empty($bytes_array[$matches[1]])) {
120
-			$bytes *= $bytes_array[$matches[1]];
121
-		} else {
122
-			return false;
123
-		}
124
-
125
-		$bytes = round($bytes);
126
-
127
-		return $bytes;
128
-	}
129
-
130
-	/**
131
-	 * Recursive copying of folders
132
-	 * @param string $src source folder
133
-	 * @param string $dest target folder
134
-	 *
135
-	 */
136
-	static function copyr($src, $dest) {
137
-		if (is_dir($src)) {
138
-			if (!is_dir($dest)) {
139
-				mkdir($dest);
140
-			}
141
-			$files = scandir($src);
142
-			foreach ($files as $file) {
143
-				if ($file != "." && $file != "..") {
144
-					self::copyr("$src/$file", "$dest/$file");
145
-				}
146
-			}
147
-		} elseif (file_exists($src) && !\OC\Files\Filesystem::isFileBlacklisted($src)) {
148
-			copy($src, $dest);
149
-		}
150
-	}
151
-
152
-	/**
153
-	 * Recursive deletion of folders
154
-	 * @param string $dir path to the folder
155
-	 * @param bool $deleteSelf if set to false only the content of the folder will be deleted
156
-	 * @return bool
157
-	 */
158
-	static function rmdirr($dir, $deleteSelf = true) {
159
-		if (is_dir($dir)) {
160
-			$files = new RecursiveIteratorIterator(
161
-				new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
162
-				RecursiveIteratorIterator::CHILD_FIRST
163
-			);
164
-
165
-			foreach ($files as $fileInfo) {
166
-				/** @var SplFileInfo $fileInfo */
167
-				if ($fileInfo->isLink()) {
168
-					unlink($fileInfo->getPathname());
169
-				} else if ($fileInfo->isDir()) {
170
-					rmdir($fileInfo->getRealPath());
171
-				} else {
172
-					unlink($fileInfo->getRealPath());
173
-				}
174
-			}
175
-			if ($deleteSelf) {
176
-				rmdir($dir);
177
-			}
178
-		} elseif (file_exists($dir)) {
179
-			if ($deleteSelf) {
180
-				unlink($dir);
181
-			}
182
-		}
183
-		if (!$deleteSelf) {
184
-			return true;
185
-		}
186
-
187
-		return !file_exists($dir);
188
-	}
189
-
190
-	/**
191
-	 * @deprecated 18.0.0
192
-	 * @return \OC\Files\Type\TemplateManager
193
-	 */
194
-	static public function getFileTemplateManager() {
195
-		if (!self::$templateManager) {
196
-			self::$templateManager = new \OC\Files\Type\TemplateManager();
197
-		}
198
-		return self::$templateManager;
199
-	}
200
-
201
-	/**
202
-	 * detect if a given program is found in the search PATH
203
-	 *
204
-	 * @param string $name
205
-	 * @param bool $path
206
-	 * @internal param string $program name
207
-	 * @internal param string $optional search path, defaults to $PATH
208
-	 * @return bool    true if executable program found in path
209
-	 */
210
-	public static function canExecute($name, $path = false) {
211
-		// path defaults to PATH from environment if not set
212
-		if ($path === false) {
213
-			$path = getenv("PATH");
214
-		}
215
-		// we look for an executable file of that name
216
-		$exts = [""];
217
-		$check_fn = "is_executable";
218
-		// Default check will be done with $path directories :
219
-		$dirs = explode(PATH_SEPARATOR, $path);
220
-		// WARNING : We have to check if open_basedir is enabled :
221
-		$obd = OC::$server->getIniWrapper()->getString('open_basedir');
222
-		if ($obd != "none") {
223
-			$obd_values = explode(PATH_SEPARATOR, $obd);
224
-			if (count($obd_values) > 0 and $obd_values[0]) {
225
-				// open_basedir is in effect !
226
-				// We need to check if the program is in one of these dirs :
227
-				$dirs = $obd_values;
228
-			}
229
-		}
230
-		foreach ($dirs as $dir) {
231
-			foreach ($exts as $ext) {
232
-				if ($check_fn("$dir/$name" . $ext))
233
-					return true;
234
-			}
235
-		}
236
-		return false;
237
-	}
238
-
239
-	/**
240
-	 * copy the contents of one stream to another
241
-	 *
242
-	 * @param resource $source
243
-	 * @param resource $target
244
-	 * @return array the number of bytes copied and result
245
-	 */
246
-	public static function streamCopy($source, $target) {
247
-		if (!$source or !$target) {
248
-			return [0, false];
249
-		}
250
-		$bufSize = 8192;
251
-		$result = true;
252
-		$count = 0;
253
-		while (!feof($source)) {
254
-			$buf = fread($source, $bufSize);
255
-			$bytesWritten = fwrite($target, $buf);
256
-			if ($bytesWritten !== false) {
257
-				$count += $bytesWritten;
258
-			}
259
-			// note: strlen is expensive so only use it when necessary,
260
-			// on the last block
261
-			if ($bytesWritten === false
262
-				|| ($bytesWritten < $bufSize && $bytesWritten < strlen($buf))
263
-			) {
264
-				// write error, could be disk full ?
265
-				$result = false;
266
-				break;
267
-			}
268
-		}
269
-		return [$count, $result];
270
-	}
271
-
272
-	/**
273
-	 * Adds a suffix to the name in case the file exists
274
-	 *
275
-	 * @param string $path
276
-	 * @param string $filename
277
-	 * @return string
278
-	 */
279
-	public static function buildNotExistingFileName($path, $filename) {
280
-		$view = \OC\Files\Filesystem::getView();
281
-		return self::buildNotExistingFileNameForView($path, $filename, $view);
282
-	}
283
-
284
-	/**
285
-	 * Adds a suffix to the name in case the file exists
286
-	 *
287
-	 * @param string $path
288
-	 * @param string $filename
289
-	 * @return string
290
-	 */
291
-	public static function buildNotExistingFileNameForView($path, $filename, \OC\Files\View $view) {
292
-		if ($path === '/') {
293
-			$path = '';
294
-		}
295
-		if ($pos = strrpos($filename, '.')) {
296
-			$name = substr($filename, 0, $pos);
297
-			$ext = substr($filename, $pos);
298
-		} else {
299
-			$name = $filename;
300
-			$ext = '';
301
-		}
302
-
303
-		$newpath = $path . '/' . $filename;
304
-		if ($view->file_exists($newpath)) {
305
-			if (preg_match_all('/\((\d+)\)/', $name, $matches, PREG_OFFSET_CAPTURE)) {
306
-				//Replace the last "(number)" with "(number+1)"
307
-				$last_match = count($matches[0]) - 1;
308
-				$counter = $matches[1][$last_match][0] + 1;
309
-				$offset = $matches[0][$last_match][1];
310
-				$match_length = strlen($matches[0][$last_match][0]);
311
-			} else {
312
-				$counter = 2;
313
-				$match_length = 0;
314
-				$offset = false;
315
-			}
316
-			do {
317
-				if ($offset) {
318
-					//Replace the last "(number)" with "(number+1)"
319
-					$newname = substr_replace($name, '(' . $counter . ')', $offset, $match_length);
320
-				} else {
321
-					$newname = $name . ' (' . $counter . ')';
322
-				}
323
-				$newpath = $path . '/' . $newname . $ext;
324
-				$counter++;
325
-			} while ($view->file_exists($newpath));
326
-		}
327
-
328
-		return $newpath;
329
-	}
330
-
331
-	/**
332
-	 * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
333
-	 *
334
-	 * @param array $input The array to work on
335
-	 * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
336
-	 * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
337
-	 * @return array
338
-	 *
339
-	 * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
340
-	 * based on http://www.php.net/manual/en/function.array-change-key-case.php#107715
341
-	 *
342
-	 */
343
-	public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') {
344
-		$case = ($case != MB_CASE_UPPER) ? MB_CASE_LOWER : MB_CASE_UPPER;
345
-		$ret = [];
346
-		foreach ($input as $k => $v) {
347
-			$ret[mb_convert_case($k, $case, $encoding)] = $v;
348
-		}
349
-		return $ret;
350
-	}
351
-
352
-	/**
353
-	 * performs a search in a nested array
354
-	 * @param array $haystack the array to be searched
355
-	 * @param string $needle the search string
356
-	 * @param mixed $index optional, only search this key name
357
-	 * @return mixed the key of the matching field, otherwise false
358
-	 *
359
-	 * performs a search in a nested array
360
-	 *
361
-	 * taken from http://www.php.net/manual/en/function.array-search.php#97645
362
-	 */
363
-	public static function recursiveArraySearch($haystack, $needle, $index = null) {
364
-		$aIt = new RecursiveArrayIterator($haystack);
365
-		$it = new RecursiveIteratorIterator($aIt);
366
-
367
-		while ($it->valid()) {
368
-			if (((isset($index) AND ($it->key() == $index)) OR !isset($index)) AND ($it->current() == $needle)) {
369
-				return $aIt->key();
370
-			}
371
-
372
-			$it->next();
373
-		}
374
-
375
-		return false;
376
-	}
377
-
378
-	/**
379
-	 * calculates the maximum upload size respecting system settings, free space and user quota
380
-	 *
381
-	 * @param string $dir the current folder where the user currently operates
382
-	 * @param int $freeSpace the number of bytes free on the storage holding $dir, if not set this will be received from the storage directly
383
-	 * @return int number of bytes representing
384
-	 */
385
-	public static function maxUploadFilesize($dir, $freeSpace = null) {
386
-		if (is_null($freeSpace) || $freeSpace < 0){
387
-			$freeSpace = self::freeSpace($dir);
388
-		}
389
-		return min($freeSpace, self::uploadLimit());
390
-	}
391
-
392
-	/**
393
-	 * Calculate free space left within user quota
394
-	 *
395
-	 * @param string $dir the current folder where the user currently operates
396
-	 * @return int number of bytes representing
397
-	 */
398
-	public static function freeSpace($dir) {
399
-		$freeSpace = \OC\Files\Filesystem::free_space($dir);
400
-		if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
401
-			$freeSpace = max($freeSpace, 0);
402
-			return $freeSpace;
403
-		} else {
404
-			return (INF > 0)? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
405
-		}
406
-	}
407
-
408
-	/**
409
-	 * Calculate PHP upload limit
410
-	 *
411
-	 * @return int PHP upload file size limit
412
-	 */
413
-	public static function uploadLimit() {
414
-		$ini = \OC::$server->getIniWrapper();
415
-		$upload_max_filesize = OCP\Util::computerFileSize($ini->get('upload_max_filesize'));
416
-		$post_max_size = OCP\Util::computerFileSize($ini->get('post_max_size'));
417
-		if ((int)$upload_max_filesize === 0 and (int)$post_max_size === 0) {
418
-			return INF;
419
-		} elseif ((int)$upload_max_filesize === 0 or (int)$post_max_size === 0) {
420
-			return max($upload_max_filesize, $post_max_size); //only the non 0 value counts
421
-		} else {
422
-			return min($upload_max_filesize, $post_max_size);
423
-		}
424
-	}
425
-
426
-	/**
427
-	 * Checks if a function is available
428
-	 *
429
-	 * @param string $function_name
430
-	 * @return bool
431
-	 */
432
-	public static function is_function_enabled($function_name) {
433
-		if (!function_exists($function_name)) {
434
-			return false;
435
-		}
436
-		$ini = \OC::$server->getIniWrapper();
437
-		$disabled = explode(',', $ini->get('disable_functions') ?: '');
438
-		$disabled = array_map('trim', $disabled);
439
-		if (in_array($function_name, $disabled)) {
440
-			return false;
441
-		}
442
-		$disabled = explode(',', $ini->get('suhosin.executor.func.blacklist') ?: '');
443
-		$disabled = array_map('trim', $disabled);
444
-		if (in_array($function_name, $disabled)) {
445
-			return false;
446
-		}
447
-		return true;
448
-	}
449
-
450
-	/**
451
-	 * Try to find a program
452
-	 *
453
-	 * @param string $program
454
-	 * @return null|string
455
-	 */
456
-	public static function findBinaryPath($program) {
457
-		$memcache = \OC::$server->getMemCacheFactory()->createDistributed('findBinaryPath');
458
-		if ($memcache->hasKey($program)) {
459
-			return $memcache->get($program);
460
-		}
461
-		$result = null;
462
-		if (self::is_function_enabled('exec')) {
463
-			$exeSniffer = new ExecutableFinder();
464
-			// Returns null if nothing is found
465
-			$result = $exeSniffer->find($program, null, ['/usr/local/sbin', '/usr/local/bin', '/usr/sbin', '/usr/bin', '/sbin', '/bin', '/opt/bin']);
466
-		}
467
-		// store the value for 5 minutes
468
-		$memcache->set($program, $result, 300);
469
-		return $result;
470
-	}
471
-
472
-	/**
473
-	 * Calculate the disc space for the given path
474
-	 *
475
-	 * @param string $path
476
-	 * @param \OCP\Files\FileInfo $rootInfo (optional)
477
-	 * @return array
478
-	 * @throws \OCP\Files\NotFoundException
479
-	 */
480
-	public static function getStorageInfo($path, $rootInfo = null) {
481
-		// return storage info without adding mount points
482
-		$includeExtStorage = \OC::$server->getSystemConfig()->getValue('quota_include_external_storage', false);
483
-
484
-		if (!$rootInfo) {
485
-			$rootInfo = \OC\Files\Filesystem::getFileInfo($path, $includeExtStorage ? 'ext' : false);
486
-		}
487
-		if (!$rootInfo instanceof \OCP\Files\FileInfo) {
488
-			throw new \OCP\Files\NotFoundException();
489
-		}
490
-		$used = $rootInfo->getSize();
491
-		if ($used < 0) {
492
-			$used = 0;
493
-		}
494
-		$quota = \OCP\Files\FileInfo::SPACE_UNLIMITED;
495
-		$storage = $rootInfo->getStorage();
496
-		$sourceStorage = $storage;
497
-		if ($storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) {
498
-			$includeExtStorage = false;
499
-			$sourceStorage = $storage->getSourceStorage();
500
-		}
501
-		if ($includeExtStorage) {
502
-			if ($storage->instanceOfStorage('\OC\Files\Storage\Home')
503
-				|| $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage')
504
-			) {
505
-				/** @var \OC\Files\Storage\Home $storage */
506
-				$userInstance = $storage->getUser();
507
-				$user = ($userInstance === null) ? null : $userInstance->getUID();
508
-			} else {
509
-				$user = \OC::$server->getUserSession()->getUser()->getUID();
510
-			}
511
-			if ($user) {
512
-				$quota = OC_Util::getUserQuota($user);
513
-			} else {
514
-				$quota = \OCP\Files\FileInfo::SPACE_UNLIMITED;
515
-			}
516
-			if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
517
-				// always get free space / total space from root + mount points
518
-				return self::getGlobalStorageInfo();
519
-			}
520
-		}
521
-
522
-		// TODO: need a better way to get total space from storage
523
-		if ($sourceStorage->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')) {
524
-			/** @var \OC\Files\Storage\Wrapper\Quota $storage */
525
-			$quota = $sourceStorage->getQuota();
526
-		}
527
-		$free = $sourceStorage->free_space($rootInfo->getInternalPath());
528
-		if ($free >= 0) {
529
-			$total = $free + $used;
530
-		} else {
531
-			$total = $free; //either unknown or unlimited
532
-		}
533
-		if ($total > 0) {
534
-			if ($quota > 0 && $total > $quota) {
535
-				$total = $quota;
536
-			}
537
-			// prevent division by zero or error codes (negative values)
538
-			$relative = round(($used / $total) * 10000) / 100;
539
-		} else {
540
-			$relative = 0;
541
-		}
542
-
543
-		$ownerId = $storage->getOwner($path);
544
-		$ownerDisplayName = '';
545
-		$owner = \OC::$server->getUserManager()->get($ownerId);
546
-		if($owner) {
547
-			$ownerDisplayName = $owner->getDisplayName();
548
-		}
549
-
550
-		return [
551
-			'free' => $free,
552
-			'used' => $used,
553
-			'quota' => $quota,
554
-			'total' => $total,
555
-			'relative' => $relative,
556
-			'owner' => $ownerId,
557
-			'ownerDisplayName' => $ownerDisplayName,
558
-		];
559
-	}
560
-
561
-	/**
562
-	 * Get storage info including all mount points and quota
563
-	 *
564
-	 * @return array
565
-	 */
566
-	private static function getGlobalStorageInfo() {
567
-		$quota = OC_Util::getUserQuota(\OCP\User::getUser());
568
-
569
-		$rootInfo = \OC\Files\Filesystem::getFileInfo('', 'ext');
570
-		$used = $rootInfo['size'];
571
-		if ($used < 0) {
572
-			$used = 0;
573
-		}
574
-
575
-		$total = $quota;
576
-		$free = $quota - $used;
577
-
578
-		if ($total > 0) {
579
-			if ($quota > 0 && $total > $quota) {
580
-				$total = $quota;
581
-			}
582
-			// prevent division by zero or error codes (negative values)
583
-			$relative = round(($used / $total) * 10000) / 100;
584
-		} else {
585
-			$relative = 0;
586
-		}
587
-
588
-		return [
589
-			'free' => $free,
590
-			'used' => $used,
591
-			'total' => $total,
592
-			'relative' => $relative,
593
-			'quota' => $quota
594
-		];
595
-	}
596
-
597
-	/**
598
-	 * Returns whether the config file is set manually to read-only
599
-	 * @return bool
600
-	 */
601
-	public static function isReadOnlyConfigEnabled() {
602
-		return \OC::$server->getConfig()->getSystemValue('config_is_read_only', false);
603
-	}
51
+    private static $templateManager;
52
+
53
+    /**
54
+     * Make a human file size
55
+     * @param int $bytes file size in bytes
56
+     * @return string a human readable file size
57
+     *
58
+     * Makes 2048 to 2 kB.
59
+     */
60
+    public static function humanFileSize($bytes) {
61
+        if ($bytes < 0) {
62
+            return "?";
63
+        }
64
+        if ($bytes < 1024) {
65
+            return "$bytes B";
66
+        }
67
+        $bytes = round($bytes / 1024, 0);
68
+        if ($bytes < 1024) {
69
+            return "$bytes KB";
70
+        }
71
+        $bytes = round($bytes / 1024, 1);
72
+        if ($bytes < 1024) {
73
+            return "$bytes MB";
74
+        }
75
+        $bytes = round($bytes / 1024, 1);
76
+        if ($bytes < 1024) {
77
+            return "$bytes GB";
78
+        }
79
+        $bytes = round($bytes / 1024, 1);
80
+        if ($bytes < 1024) {
81
+            return "$bytes TB";
82
+        }
83
+
84
+        $bytes = round($bytes / 1024, 1);
85
+        return "$bytes PB";
86
+    }
87
+
88
+    /**
89
+     * Make a computer file size
90
+     * @param string $str file size in human readable format
91
+     * @return float|bool a file size in bytes
92
+     *
93
+     * Makes 2kB to 2048.
94
+     *
95
+     * Inspired by: http://www.php.net/manual/en/function.filesize.php#92418
96
+     */
97
+    public static function computerFileSize($str) {
98
+        $str = strtolower($str);
99
+        if (is_numeric($str)) {
100
+            return (float)$str;
101
+        }
102
+
103
+        $bytes_array = [
104
+            'b' => 1,
105
+            'k' => 1024,
106
+            'kb' => 1024,
107
+            'mb' => 1024 * 1024,
108
+            'm' => 1024 * 1024,
109
+            'gb' => 1024 * 1024 * 1024,
110
+            'g' => 1024 * 1024 * 1024,
111
+            'tb' => 1024 * 1024 * 1024 * 1024,
112
+            't' => 1024 * 1024 * 1024 * 1024,
113
+            'pb' => 1024 * 1024 * 1024 * 1024 * 1024,
114
+            'p' => 1024 * 1024 * 1024 * 1024 * 1024,
115
+        ];
116
+
117
+        $bytes = (float)$str;
118
+
119
+        if (preg_match('#([kmgtp]?b?)$#si', $str, $matches) && !empty($bytes_array[$matches[1]])) {
120
+            $bytes *= $bytes_array[$matches[1]];
121
+        } else {
122
+            return false;
123
+        }
124
+
125
+        $bytes = round($bytes);
126
+
127
+        return $bytes;
128
+    }
129
+
130
+    /**
131
+     * Recursive copying of folders
132
+     * @param string $src source folder
133
+     * @param string $dest target folder
134
+     *
135
+     */
136
+    static function copyr($src, $dest) {
137
+        if (is_dir($src)) {
138
+            if (!is_dir($dest)) {
139
+                mkdir($dest);
140
+            }
141
+            $files = scandir($src);
142
+            foreach ($files as $file) {
143
+                if ($file != "." && $file != "..") {
144
+                    self::copyr("$src/$file", "$dest/$file");
145
+                }
146
+            }
147
+        } elseif (file_exists($src) && !\OC\Files\Filesystem::isFileBlacklisted($src)) {
148
+            copy($src, $dest);
149
+        }
150
+    }
151
+
152
+    /**
153
+     * Recursive deletion of folders
154
+     * @param string $dir path to the folder
155
+     * @param bool $deleteSelf if set to false only the content of the folder will be deleted
156
+     * @return bool
157
+     */
158
+    static function rmdirr($dir, $deleteSelf = true) {
159
+        if (is_dir($dir)) {
160
+            $files = new RecursiveIteratorIterator(
161
+                new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
162
+                RecursiveIteratorIterator::CHILD_FIRST
163
+            );
164
+
165
+            foreach ($files as $fileInfo) {
166
+                /** @var SplFileInfo $fileInfo */
167
+                if ($fileInfo->isLink()) {
168
+                    unlink($fileInfo->getPathname());
169
+                } else if ($fileInfo->isDir()) {
170
+                    rmdir($fileInfo->getRealPath());
171
+                } else {
172
+                    unlink($fileInfo->getRealPath());
173
+                }
174
+            }
175
+            if ($deleteSelf) {
176
+                rmdir($dir);
177
+            }
178
+        } elseif (file_exists($dir)) {
179
+            if ($deleteSelf) {
180
+                unlink($dir);
181
+            }
182
+        }
183
+        if (!$deleteSelf) {
184
+            return true;
185
+        }
186
+
187
+        return !file_exists($dir);
188
+    }
189
+
190
+    /**
191
+     * @deprecated 18.0.0
192
+     * @return \OC\Files\Type\TemplateManager
193
+     */
194
+    static public function getFileTemplateManager() {
195
+        if (!self::$templateManager) {
196
+            self::$templateManager = new \OC\Files\Type\TemplateManager();
197
+        }
198
+        return self::$templateManager;
199
+    }
200
+
201
+    /**
202
+     * detect if a given program is found in the search PATH
203
+     *
204
+     * @param string $name
205
+     * @param bool $path
206
+     * @internal param string $program name
207
+     * @internal param string $optional search path, defaults to $PATH
208
+     * @return bool    true if executable program found in path
209
+     */
210
+    public static function canExecute($name, $path = false) {
211
+        // path defaults to PATH from environment if not set
212
+        if ($path === false) {
213
+            $path = getenv("PATH");
214
+        }
215
+        // we look for an executable file of that name
216
+        $exts = [""];
217
+        $check_fn = "is_executable";
218
+        // Default check will be done with $path directories :
219
+        $dirs = explode(PATH_SEPARATOR, $path);
220
+        // WARNING : We have to check if open_basedir is enabled :
221
+        $obd = OC::$server->getIniWrapper()->getString('open_basedir');
222
+        if ($obd != "none") {
223
+            $obd_values = explode(PATH_SEPARATOR, $obd);
224
+            if (count($obd_values) > 0 and $obd_values[0]) {
225
+                // open_basedir is in effect !
226
+                // We need to check if the program is in one of these dirs :
227
+                $dirs = $obd_values;
228
+            }
229
+        }
230
+        foreach ($dirs as $dir) {
231
+            foreach ($exts as $ext) {
232
+                if ($check_fn("$dir/$name" . $ext))
233
+                    return true;
234
+            }
235
+        }
236
+        return false;
237
+    }
238
+
239
+    /**
240
+     * copy the contents of one stream to another
241
+     *
242
+     * @param resource $source
243
+     * @param resource $target
244
+     * @return array the number of bytes copied and result
245
+     */
246
+    public static function streamCopy($source, $target) {
247
+        if (!$source or !$target) {
248
+            return [0, false];
249
+        }
250
+        $bufSize = 8192;
251
+        $result = true;
252
+        $count = 0;
253
+        while (!feof($source)) {
254
+            $buf = fread($source, $bufSize);
255
+            $bytesWritten = fwrite($target, $buf);
256
+            if ($bytesWritten !== false) {
257
+                $count += $bytesWritten;
258
+            }
259
+            // note: strlen is expensive so only use it when necessary,
260
+            // on the last block
261
+            if ($bytesWritten === false
262
+                || ($bytesWritten < $bufSize && $bytesWritten < strlen($buf))
263
+            ) {
264
+                // write error, could be disk full ?
265
+                $result = false;
266
+                break;
267
+            }
268
+        }
269
+        return [$count, $result];
270
+    }
271
+
272
+    /**
273
+     * Adds a suffix to the name in case the file exists
274
+     *
275
+     * @param string $path
276
+     * @param string $filename
277
+     * @return string
278
+     */
279
+    public static function buildNotExistingFileName($path, $filename) {
280
+        $view = \OC\Files\Filesystem::getView();
281
+        return self::buildNotExistingFileNameForView($path, $filename, $view);
282
+    }
283
+
284
+    /**
285
+     * Adds a suffix to the name in case the file exists
286
+     *
287
+     * @param string $path
288
+     * @param string $filename
289
+     * @return string
290
+     */
291
+    public static function buildNotExistingFileNameForView($path, $filename, \OC\Files\View $view) {
292
+        if ($path === '/') {
293
+            $path = '';
294
+        }
295
+        if ($pos = strrpos($filename, '.')) {
296
+            $name = substr($filename, 0, $pos);
297
+            $ext = substr($filename, $pos);
298
+        } else {
299
+            $name = $filename;
300
+            $ext = '';
301
+        }
302
+
303
+        $newpath = $path . '/' . $filename;
304
+        if ($view->file_exists($newpath)) {
305
+            if (preg_match_all('/\((\d+)\)/', $name, $matches, PREG_OFFSET_CAPTURE)) {
306
+                //Replace the last "(number)" with "(number+1)"
307
+                $last_match = count($matches[0]) - 1;
308
+                $counter = $matches[1][$last_match][0] + 1;
309
+                $offset = $matches[0][$last_match][1];
310
+                $match_length = strlen($matches[0][$last_match][0]);
311
+            } else {
312
+                $counter = 2;
313
+                $match_length = 0;
314
+                $offset = false;
315
+            }
316
+            do {
317
+                if ($offset) {
318
+                    //Replace the last "(number)" with "(number+1)"
319
+                    $newname = substr_replace($name, '(' . $counter . ')', $offset, $match_length);
320
+                } else {
321
+                    $newname = $name . ' (' . $counter . ')';
322
+                }
323
+                $newpath = $path . '/' . $newname . $ext;
324
+                $counter++;
325
+            } while ($view->file_exists($newpath));
326
+        }
327
+
328
+        return $newpath;
329
+    }
330
+
331
+    /**
332
+     * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
333
+     *
334
+     * @param array $input The array to work on
335
+     * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
336
+     * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
337
+     * @return array
338
+     *
339
+     * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
340
+     * based on http://www.php.net/manual/en/function.array-change-key-case.php#107715
341
+     *
342
+     */
343
+    public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') {
344
+        $case = ($case != MB_CASE_UPPER) ? MB_CASE_LOWER : MB_CASE_UPPER;
345
+        $ret = [];
346
+        foreach ($input as $k => $v) {
347
+            $ret[mb_convert_case($k, $case, $encoding)] = $v;
348
+        }
349
+        return $ret;
350
+    }
351
+
352
+    /**
353
+     * performs a search in a nested array
354
+     * @param array $haystack the array to be searched
355
+     * @param string $needle the search string
356
+     * @param mixed $index optional, only search this key name
357
+     * @return mixed the key of the matching field, otherwise false
358
+     *
359
+     * performs a search in a nested array
360
+     *
361
+     * taken from http://www.php.net/manual/en/function.array-search.php#97645
362
+     */
363
+    public static function recursiveArraySearch($haystack, $needle, $index = null) {
364
+        $aIt = new RecursiveArrayIterator($haystack);
365
+        $it = new RecursiveIteratorIterator($aIt);
366
+
367
+        while ($it->valid()) {
368
+            if (((isset($index) AND ($it->key() == $index)) OR !isset($index)) AND ($it->current() == $needle)) {
369
+                return $aIt->key();
370
+            }
371
+
372
+            $it->next();
373
+        }
374
+
375
+        return false;
376
+    }
377
+
378
+    /**
379
+     * calculates the maximum upload size respecting system settings, free space and user quota
380
+     *
381
+     * @param string $dir the current folder where the user currently operates
382
+     * @param int $freeSpace the number of bytes free on the storage holding $dir, if not set this will be received from the storage directly
383
+     * @return int number of bytes representing
384
+     */
385
+    public static function maxUploadFilesize($dir, $freeSpace = null) {
386
+        if (is_null($freeSpace) || $freeSpace < 0){
387
+            $freeSpace = self::freeSpace($dir);
388
+        }
389
+        return min($freeSpace, self::uploadLimit());
390
+    }
391
+
392
+    /**
393
+     * Calculate free space left within user quota
394
+     *
395
+     * @param string $dir the current folder where the user currently operates
396
+     * @return int number of bytes representing
397
+     */
398
+    public static function freeSpace($dir) {
399
+        $freeSpace = \OC\Files\Filesystem::free_space($dir);
400
+        if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
401
+            $freeSpace = max($freeSpace, 0);
402
+            return $freeSpace;
403
+        } else {
404
+            return (INF > 0)? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
405
+        }
406
+    }
407
+
408
+    /**
409
+     * Calculate PHP upload limit
410
+     *
411
+     * @return int PHP upload file size limit
412
+     */
413
+    public static function uploadLimit() {
414
+        $ini = \OC::$server->getIniWrapper();
415
+        $upload_max_filesize = OCP\Util::computerFileSize($ini->get('upload_max_filesize'));
416
+        $post_max_size = OCP\Util::computerFileSize($ini->get('post_max_size'));
417
+        if ((int)$upload_max_filesize === 0 and (int)$post_max_size === 0) {
418
+            return INF;
419
+        } elseif ((int)$upload_max_filesize === 0 or (int)$post_max_size === 0) {
420
+            return max($upload_max_filesize, $post_max_size); //only the non 0 value counts
421
+        } else {
422
+            return min($upload_max_filesize, $post_max_size);
423
+        }
424
+    }
425
+
426
+    /**
427
+     * Checks if a function is available
428
+     *
429
+     * @param string $function_name
430
+     * @return bool
431
+     */
432
+    public static function is_function_enabled($function_name) {
433
+        if (!function_exists($function_name)) {
434
+            return false;
435
+        }
436
+        $ini = \OC::$server->getIniWrapper();
437
+        $disabled = explode(',', $ini->get('disable_functions') ?: '');
438
+        $disabled = array_map('trim', $disabled);
439
+        if (in_array($function_name, $disabled)) {
440
+            return false;
441
+        }
442
+        $disabled = explode(',', $ini->get('suhosin.executor.func.blacklist') ?: '');
443
+        $disabled = array_map('trim', $disabled);
444
+        if (in_array($function_name, $disabled)) {
445
+            return false;
446
+        }
447
+        return true;
448
+    }
449
+
450
+    /**
451
+     * Try to find a program
452
+     *
453
+     * @param string $program
454
+     * @return null|string
455
+     */
456
+    public static function findBinaryPath($program) {
457
+        $memcache = \OC::$server->getMemCacheFactory()->createDistributed('findBinaryPath');
458
+        if ($memcache->hasKey($program)) {
459
+            return $memcache->get($program);
460
+        }
461
+        $result = null;
462
+        if (self::is_function_enabled('exec')) {
463
+            $exeSniffer = new ExecutableFinder();
464
+            // Returns null if nothing is found
465
+            $result = $exeSniffer->find($program, null, ['/usr/local/sbin', '/usr/local/bin', '/usr/sbin', '/usr/bin', '/sbin', '/bin', '/opt/bin']);
466
+        }
467
+        // store the value for 5 minutes
468
+        $memcache->set($program, $result, 300);
469
+        return $result;
470
+    }
471
+
472
+    /**
473
+     * Calculate the disc space for the given path
474
+     *
475
+     * @param string $path
476
+     * @param \OCP\Files\FileInfo $rootInfo (optional)
477
+     * @return array
478
+     * @throws \OCP\Files\NotFoundException
479
+     */
480
+    public static function getStorageInfo($path, $rootInfo = null) {
481
+        // return storage info without adding mount points
482
+        $includeExtStorage = \OC::$server->getSystemConfig()->getValue('quota_include_external_storage', false);
483
+
484
+        if (!$rootInfo) {
485
+            $rootInfo = \OC\Files\Filesystem::getFileInfo($path, $includeExtStorage ? 'ext' : false);
486
+        }
487
+        if (!$rootInfo instanceof \OCP\Files\FileInfo) {
488
+            throw new \OCP\Files\NotFoundException();
489
+        }
490
+        $used = $rootInfo->getSize();
491
+        if ($used < 0) {
492
+            $used = 0;
493
+        }
494
+        $quota = \OCP\Files\FileInfo::SPACE_UNLIMITED;
495
+        $storage = $rootInfo->getStorage();
496
+        $sourceStorage = $storage;
497
+        if ($storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) {
498
+            $includeExtStorage = false;
499
+            $sourceStorage = $storage->getSourceStorage();
500
+        }
501
+        if ($includeExtStorage) {
502
+            if ($storage->instanceOfStorage('\OC\Files\Storage\Home')
503
+                || $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage')
504
+            ) {
505
+                /** @var \OC\Files\Storage\Home $storage */
506
+                $userInstance = $storage->getUser();
507
+                $user = ($userInstance === null) ? null : $userInstance->getUID();
508
+            } else {
509
+                $user = \OC::$server->getUserSession()->getUser()->getUID();
510
+            }
511
+            if ($user) {
512
+                $quota = OC_Util::getUserQuota($user);
513
+            } else {
514
+                $quota = \OCP\Files\FileInfo::SPACE_UNLIMITED;
515
+            }
516
+            if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
517
+                // always get free space / total space from root + mount points
518
+                return self::getGlobalStorageInfo();
519
+            }
520
+        }
521
+
522
+        // TODO: need a better way to get total space from storage
523
+        if ($sourceStorage->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')) {
524
+            /** @var \OC\Files\Storage\Wrapper\Quota $storage */
525
+            $quota = $sourceStorage->getQuota();
526
+        }
527
+        $free = $sourceStorage->free_space($rootInfo->getInternalPath());
528
+        if ($free >= 0) {
529
+            $total = $free + $used;
530
+        } else {
531
+            $total = $free; //either unknown or unlimited
532
+        }
533
+        if ($total > 0) {
534
+            if ($quota > 0 && $total > $quota) {
535
+                $total = $quota;
536
+            }
537
+            // prevent division by zero or error codes (negative values)
538
+            $relative = round(($used / $total) * 10000) / 100;
539
+        } else {
540
+            $relative = 0;
541
+        }
542
+
543
+        $ownerId = $storage->getOwner($path);
544
+        $ownerDisplayName = '';
545
+        $owner = \OC::$server->getUserManager()->get($ownerId);
546
+        if($owner) {
547
+            $ownerDisplayName = $owner->getDisplayName();
548
+        }
549
+
550
+        return [
551
+            'free' => $free,
552
+            'used' => $used,
553
+            'quota' => $quota,
554
+            'total' => $total,
555
+            'relative' => $relative,
556
+            'owner' => $ownerId,
557
+            'ownerDisplayName' => $ownerDisplayName,
558
+        ];
559
+    }
560
+
561
+    /**
562
+     * Get storage info including all mount points and quota
563
+     *
564
+     * @return array
565
+     */
566
+    private static function getGlobalStorageInfo() {
567
+        $quota = OC_Util::getUserQuota(\OCP\User::getUser());
568
+
569
+        $rootInfo = \OC\Files\Filesystem::getFileInfo('', 'ext');
570
+        $used = $rootInfo['size'];
571
+        if ($used < 0) {
572
+            $used = 0;
573
+        }
574
+
575
+        $total = $quota;
576
+        $free = $quota - $used;
577
+
578
+        if ($total > 0) {
579
+            if ($quota > 0 && $total > $quota) {
580
+                $total = $quota;
581
+            }
582
+            // prevent division by zero or error codes (negative values)
583
+            $relative = round(($used / $total) * 10000) / 100;
584
+        } else {
585
+            $relative = 0;
586
+        }
587
+
588
+        return [
589
+            'free' => $free,
590
+            'used' => $used,
591
+            'total' => $total,
592
+            'relative' => $relative,
593
+            'quota' => $quota
594
+        ];
595
+    }
596
+
597
+    /**
598
+     * Returns whether the config file is set manually to read-only
599
+     * @return bool
600
+     */
601
+    public static function isReadOnlyConfigEnabled() {
602
+        return \OC::$server->getConfig()->getSystemValue('config_is_read_only', false);
603
+    }
604 604
 }
Please login to merge, or discard this patch.
lib/private/legacy/util.php 1 patch
Indentation   +1395 added lines, -1395 removed lines patch added patch discarded remove patch
@@ -69,1405 +69,1405 @@
 block discarded – undo
69 69
 use OCP\IUser;
70 70
 
71 71
 class OC_Util {
72
-	public static $scripts = [];
73
-	public static $styles = [];
74
-	public static $headers = [];
75
-	private static $rootMounted = false;
76
-	private static $fsSetup = false;
77
-
78
-	/** @var array Local cache of version.php */
79
-	private static $versionCache = null;
80
-
81
-	protected static function getAppManager() {
82
-		return \OC::$server->getAppManager();
83
-	}
84
-
85
-	private static function initLocalStorageRootFS() {
86
-		// mount local file backend as root
87
-		$configDataDirectory = \OC::$server->getSystemConfig()->getValue("datadirectory", OC::$SERVERROOT . "/data");
88
-		//first set up the local "root" storage
89
-		\OC\Files\Filesystem::initMountManager();
90
-		if (!self::$rootMounted) {
91
-			\OC\Files\Filesystem::mount('\OC\Files\Storage\Local', ['datadir' => $configDataDirectory], '/');
92
-			self::$rootMounted = true;
93
-		}
94
-	}
95
-
96
-	/**
97
-	 * mounting an object storage as the root fs will in essence remove the
98
-	 * necessity of a data folder being present.
99
-	 * TODO make home storage aware of this and use the object storage instead of local disk access
100
-	 *
101
-	 * @param array $config containing 'class' and optional 'arguments'
102
-	 * @suppress PhanDeprecatedFunction
103
-	 */
104
-	private static function initObjectStoreRootFS($config) {
105
-		// check misconfiguration
106
-		if (empty($config['class'])) {
107
-			\OCP\Util::writeLog('files', 'No class given for objectstore', ILogger::ERROR);
108
-		}
109
-		if (!isset($config['arguments'])) {
110
-			$config['arguments'] = [];
111
-		}
112
-
113
-		// instantiate object store implementation
114
-		$name = $config['class'];
115
-		if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) {
116
-			$segments = explode('\\', $name);
117
-			OC_App::loadApp(strtolower($segments[1]));
118
-		}
119
-		$config['arguments']['objectstore'] = new $config['class']($config['arguments']);
120
-		// mount with plain / root object store implementation
121
-		$config['class'] = '\OC\Files\ObjectStore\ObjectStoreStorage';
122
-
123
-		// mount object storage as root
124
-		\OC\Files\Filesystem::initMountManager();
125
-		if (!self::$rootMounted) {
126
-			\OC\Files\Filesystem::mount($config['class'], $config['arguments'], '/');
127
-			self::$rootMounted = true;
128
-		}
129
-	}
130
-
131
-	/**
132
-	 * mounting an object storage as the root fs will in essence remove the
133
-	 * necessity of a data folder being present.
134
-	 *
135
-	 * @param array $config containing 'class' and optional 'arguments'
136
-	 * @suppress PhanDeprecatedFunction
137
-	 */
138
-	private static function initObjectStoreMultibucketRootFS($config) {
139
-		// check misconfiguration
140
-		if (empty($config['class'])) {
141
-			\OCP\Util::writeLog('files', 'No class given for objectstore', ILogger::ERROR);
142
-		}
143
-		if (!isset($config['arguments'])) {
144
-			$config['arguments'] = [];
145
-		}
146
-
147
-		// instantiate object store implementation
148
-		$name = $config['class'];
149
-		if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) {
150
-			$segments = explode('\\', $name);
151
-			OC_App::loadApp(strtolower($segments[1]));
152
-		}
153
-
154
-		if (!isset($config['arguments']['bucket'])) {
155
-			$config['arguments']['bucket'] = '';
156
-		}
157
-		// put the root FS always in first bucket for multibucket configuration
158
-		$config['arguments']['bucket'] .= '0';
159
-
160
-		$config['arguments']['objectstore'] = new $config['class']($config['arguments']);
161
-		// mount with plain / root object store implementation
162
-		$config['class'] = '\OC\Files\ObjectStore\ObjectStoreStorage';
163
-
164
-		// mount object storage as root
165
-		\OC\Files\Filesystem::initMountManager();
166
-		if (!self::$rootMounted) {
167
-			\OC\Files\Filesystem::mount($config['class'], $config['arguments'], '/');
168
-			self::$rootMounted = true;
169
-		}
170
-	}
171
-
172
-	/**
173
-	 * Can be set up
174
-	 *
175
-	 * @param string $user
176
-	 * @return boolean
177
-	 * @description configure the initial filesystem based on the configuration
178
-	 * @suppress PhanDeprecatedFunction
179
-	 * @suppress PhanAccessMethodInternal
180
-	 */
181
-	public static function setupFS($user = '') {
182
-		//setting up the filesystem twice can only lead to trouble
183
-		if (self::$fsSetup) {
184
-			return false;
185
-		}
186
-
187
-		\OC::$server->getEventLogger()->start('setup_fs', 'Setup filesystem');
188
-
189
-		// If we are not forced to load a specific user we load the one that is logged in
190
-		if ($user === null) {
191
-			$user = '';
192
-		} else if ($user == "" && \OC::$server->getUserSession()->isLoggedIn()) {
193
-			$user = OC_User::getUser();
194
-		}
195
-
196
-		// load all filesystem apps before, so no setup-hook gets lost
197
-		OC_App::loadApps(['filesystem']);
198
-
199
-		// the filesystem will finish when $user is not empty,
200
-		// mark fs setup here to avoid doing the setup from loading
201
-		// OC_Filesystem
202
-		if ($user != '') {
203
-			self::$fsSetup = true;
204
-		}
205
-
206
-		\OC\Files\Filesystem::initMountManager();
207
-
208
-		$prevLogging = \OC\Files\Filesystem::logWarningWhenAddingStorageWrapper(false);
209
-		\OC\Files\Filesystem::addStorageWrapper('mount_options', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) {
210
-			if ($storage->instanceOfStorage('\OC\Files\Storage\Common')) {
211
-				/** @var \OC\Files\Storage\Common $storage */
212
-				$storage->setMountOptions($mount->getOptions());
213
-			}
214
-			return $storage;
215
-		});
216
-
217
-		\OC\Files\Filesystem::addStorageWrapper('enable_sharing', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) {
218
-			if (!$mount->getOption('enable_sharing', true)) {
219
-				return new \OC\Files\Storage\Wrapper\PermissionsMask([
220
-					'storage' => $storage,
221
-					'mask' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_SHARE
222
-				]);
223
-			}
224
-			return $storage;
225
-		});
226
-
227
-		// install storage availability wrapper, before most other wrappers
228
-		\OC\Files\Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, \OCP\Files\Storage\IStorage $storage) {
229
-			if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
230
-				return new \OC\Files\Storage\Wrapper\Availability(['storage' => $storage]);
231
-			}
232
-			return $storage;
233
-		});
234
-
235
-		\OC\Files\Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) {
236
-			if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
237
-				return new \OC\Files\Storage\Wrapper\Encoding(['storage' => $storage]);
238
-			}
239
-			return $storage;
240
-		});
241
-
242
-		\OC\Files\Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage) {
243
-			// set up quota for home storages, even for other users
244
-			// which can happen when using sharing
245
-
246
-			/**
247
-			 * @var \OC\Files\Storage\Storage $storage
248
-			 */
249
-			if ($storage->instanceOfStorage('\OC\Files\Storage\Home')
250
-				|| $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage')
251
-			) {
252
-				/** @var \OC\Files\Storage\Home $storage */
253
-				if (is_object($storage->getUser())) {
254
-					$user = $storage->getUser()->getUID();
255
-					$quota = OC_Util::getUserQuota($user);
256
-					if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
257
-						return new \OC\Files\Storage\Wrapper\Quota(['storage' => $storage, 'quota' => $quota, 'root' => 'files']);
258
-					}
259
-				}
260
-			}
261
-
262
-			return $storage;
263
-		});
264
-
265
-		\OC\Files\Filesystem::addStorageWrapper('readonly', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) {
266
-			/*
72
+    public static $scripts = [];
73
+    public static $styles = [];
74
+    public static $headers = [];
75
+    private static $rootMounted = false;
76
+    private static $fsSetup = false;
77
+
78
+    /** @var array Local cache of version.php */
79
+    private static $versionCache = null;
80
+
81
+    protected static function getAppManager() {
82
+        return \OC::$server->getAppManager();
83
+    }
84
+
85
+    private static function initLocalStorageRootFS() {
86
+        // mount local file backend as root
87
+        $configDataDirectory = \OC::$server->getSystemConfig()->getValue("datadirectory", OC::$SERVERROOT . "/data");
88
+        //first set up the local "root" storage
89
+        \OC\Files\Filesystem::initMountManager();
90
+        if (!self::$rootMounted) {
91
+            \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', ['datadir' => $configDataDirectory], '/');
92
+            self::$rootMounted = true;
93
+        }
94
+    }
95
+
96
+    /**
97
+     * mounting an object storage as the root fs will in essence remove the
98
+     * necessity of a data folder being present.
99
+     * TODO make home storage aware of this and use the object storage instead of local disk access
100
+     *
101
+     * @param array $config containing 'class' and optional 'arguments'
102
+     * @suppress PhanDeprecatedFunction
103
+     */
104
+    private static function initObjectStoreRootFS($config) {
105
+        // check misconfiguration
106
+        if (empty($config['class'])) {
107
+            \OCP\Util::writeLog('files', 'No class given for objectstore', ILogger::ERROR);
108
+        }
109
+        if (!isset($config['arguments'])) {
110
+            $config['arguments'] = [];
111
+        }
112
+
113
+        // instantiate object store implementation
114
+        $name = $config['class'];
115
+        if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) {
116
+            $segments = explode('\\', $name);
117
+            OC_App::loadApp(strtolower($segments[1]));
118
+        }
119
+        $config['arguments']['objectstore'] = new $config['class']($config['arguments']);
120
+        // mount with plain / root object store implementation
121
+        $config['class'] = '\OC\Files\ObjectStore\ObjectStoreStorage';
122
+
123
+        // mount object storage as root
124
+        \OC\Files\Filesystem::initMountManager();
125
+        if (!self::$rootMounted) {
126
+            \OC\Files\Filesystem::mount($config['class'], $config['arguments'], '/');
127
+            self::$rootMounted = true;
128
+        }
129
+    }
130
+
131
+    /**
132
+     * mounting an object storage as the root fs will in essence remove the
133
+     * necessity of a data folder being present.
134
+     *
135
+     * @param array $config containing 'class' and optional 'arguments'
136
+     * @suppress PhanDeprecatedFunction
137
+     */
138
+    private static function initObjectStoreMultibucketRootFS($config) {
139
+        // check misconfiguration
140
+        if (empty($config['class'])) {
141
+            \OCP\Util::writeLog('files', 'No class given for objectstore', ILogger::ERROR);
142
+        }
143
+        if (!isset($config['arguments'])) {
144
+            $config['arguments'] = [];
145
+        }
146
+
147
+        // instantiate object store implementation
148
+        $name = $config['class'];
149
+        if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) {
150
+            $segments = explode('\\', $name);
151
+            OC_App::loadApp(strtolower($segments[1]));
152
+        }
153
+
154
+        if (!isset($config['arguments']['bucket'])) {
155
+            $config['arguments']['bucket'] = '';
156
+        }
157
+        // put the root FS always in first bucket for multibucket configuration
158
+        $config['arguments']['bucket'] .= '0';
159
+
160
+        $config['arguments']['objectstore'] = new $config['class']($config['arguments']);
161
+        // mount with plain / root object store implementation
162
+        $config['class'] = '\OC\Files\ObjectStore\ObjectStoreStorage';
163
+
164
+        // mount object storage as root
165
+        \OC\Files\Filesystem::initMountManager();
166
+        if (!self::$rootMounted) {
167
+            \OC\Files\Filesystem::mount($config['class'], $config['arguments'], '/');
168
+            self::$rootMounted = true;
169
+        }
170
+    }
171
+
172
+    /**
173
+     * Can be set up
174
+     *
175
+     * @param string $user
176
+     * @return boolean
177
+     * @description configure the initial filesystem based on the configuration
178
+     * @suppress PhanDeprecatedFunction
179
+     * @suppress PhanAccessMethodInternal
180
+     */
181
+    public static function setupFS($user = '') {
182
+        //setting up the filesystem twice can only lead to trouble
183
+        if (self::$fsSetup) {
184
+            return false;
185
+        }
186
+
187
+        \OC::$server->getEventLogger()->start('setup_fs', 'Setup filesystem');
188
+
189
+        // If we are not forced to load a specific user we load the one that is logged in
190
+        if ($user === null) {
191
+            $user = '';
192
+        } else if ($user == "" && \OC::$server->getUserSession()->isLoggedIn()) {
193
+            $user = OC_User::getUser();
194
+        }
195
+
196
+        // load all filesystem apps before, so no setup-hook gets lost
197
+        OC_App::loadApps(['filesystem']);
198
+
199
+        // the filesystem will finish when $user is not empty,
200
+        // mark fs setup here to avoid doing the setup from loading
201
+        // OC_Filesystem
202
+        if ($user != '') {
203
+            self::$fsSetup = true;
204
+        }
205
+
206
+        \OC\Files\Filesystem::initMountManager();
207
+
208
+        $prevLogging = \OC\Files\Filesystem::logWarningWhenAddingStorageWrapper(false);
209
+        \OC\Files\Filesystem::addStorageWrapper('mount_options', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) {
210
+            if ($storage->instanceOfStorage('\OC\Files\Storage\Common')) {
211
+                /** @var \OC\Files\Storage\Common $storage */
212
+                $storage->setMountOptions($mount->getOptions());
213
+            }
214
+            return $storage;
215
+        });
216
+
217
+        \OC\Files\Filesystem::addStorageWrapper('enable_sharing', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) {
218
+            if (!$mount->getOption('enable_sharing', true)) {
219
+                return new \OC\Files\Storage\Wrapper\PermissionsMask([
220
+                    'storage' => $storage,
221
+                    'mask' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_SHARE
222
+                ]);
223
+            }
224
+            return $storage;
225
+        });
226
+
227
+        // install storage availability wrapper, before most other wrappers
228
+        \OC\Files\Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, \OCP\Files\Storage\IStorage $storage) {
229
+            if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
230
+                return new \OC\Files\Storage\Wrapper\Availability(['storage' => $storage]);
231
+            }
232
+            return $storage;
233
+        });
234
+
235
+        \OC\Files\Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) {
236
+            if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
237
+                return new \OC\Files\Storage\Wrapper\Encoding(['storage' => $storage]);
238
+            }
239
+            return $storage;
240
+        });
241
+
242
+        \OC\Files\Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage) {
243
+            // set up quota for home storages, even for other users
244
+            // which can happen when using sharing
245
+
246
+            /**
247
+             * @var \OC\Files\Storage\Storage $storage
248
+             */
249
+            if ($storage->instanceOfStorage('\OC\Files\Storage\Home')
250
+                || $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage')
251
+            ) {
252
+                /** @var \OC\Files\Storage\Home $storage */
253
+                if (is_object($storage->getUser())) {
254
+                    $user = $storage->getUser()->getUID();
255
+                    $quota = OC_Util::getUserQuota($user);
256
+                    if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
257
+                        return new \OC\Files\Storage\Wrapper\Quota(['storage' => $storage, 'quota' => $quota, 'root' => 'files']);
258
+                    }
259
+                }
260
+            }
261
+
262
+            return $storage;
263
+        });
264
+
265
+        \OC\Files\Filesystem::addStorageWrapper('readonly', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) {
266
+            /*
267 267
 			 * Do not allow any operations that modify the storage
268 268
 			 */
269
-			if ($mount->getOption('readonly', false)) {
270
-				return new \OC\Files\Storage\Wrapper\PermissionsMask([
271
-					'storage' => $storage,
272
-					'mask' => \OCP\Constants::PERMISSION_ALL & ~(
273
-						\OCP\Constants::PERMISSION_UPDATE |
274
-						\OCP\Constants::PERMISSION_CREATE |
275
-						\OCP\Constants::PERMISSION_DELETE
276
-					),
277
-				]);
278
-			}
279
-			return $storage;
280
-		});
281
-
282
-		OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user]);
283
-
284
-		\OC\Files\Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
285
-
286
-		//check if we are using an object storage
287
-		$objectStore = \OC::$server->getSystemConfig()->getValue('objectstore', null);
288
-		$objectStoreMultibucket = \OC::$server->getSystemConfig()->getValue('objectstore_multibucket', null);
289
-
290
-		// use the same order as in ObjectHomeMountProvider
291
-		if (isset($objectStoreMultibucket)) {
292
-			self::initObjectStoreMultibucketRootFS($objectStoreMultibucket);
293
-		} elseif (isset($objectStore)) {
294
-			self::initObjectStoreRootFS($objectStore);
295
-		} else {
296
-			self::initLocalStorageRootFS();
297
-		}
298
-
299
-		if ($user != '' && !\OC::$server->getUserManager()->userExists($user)) {
300
-			\OC::$server->getEventLogger()->end('setup_fs');
301
-			return false;
302
-		}
303
-
304
-		//if we aren't logged in, there is no use to set up the filesystem
305
-		if ($user != "") {
306
-
307
-			$userDir = '/' . $user . '/files';
308
-
309
-			//jail the user into his "home" directory
310
-			\OC\Files\Filesystem::init($user, $userDir);
311
-
312
-			OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $user, 'user_dir' => $userDir]);
313
-		}
314
-		\OC::$server->getEventLogger()->end('setup_fs');
315
-		return true;
316
-	}
317
-
318
-	/**
319
-	 * check if a password is required for each public link
320
-	 *
321
-	 * @return boolean
322
-	 * @suppress PhanDeprecatedFunction
323
-	 */
324
-	public static function isPublicLinkPasswordRequired() {
325
-		$enforcePassword = \OC::$server->getConfig()->getAppValue('core', 'shareapi_enforce_links_password', 'no');
326
-		return $enforcePassword === 'yes';
327
-	}
328
-
329
-	/**
330
-	 * check if sharing is disabled for the current user
331
-	 * @param IConfig $config
332
-	 * @param IGroupManager $groupManager
333
-	 * @param IUser|null $user
334
-	 * @return bool
335
-	 */
336
-	public static function isSharingDisabledForUser(IConfig $config, IGroupManager $groupManager, $user) {
337
-		if ($config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
338
-			$groupsList = $config->getAppValue('core', 'shareapi_exclude_groups_list', '');
339
-			$excludedGroups = json_decode($groupsList);
340
-			if (is_null($excludedGroups)) {
341
-				$excludedGroups = explode(',', $groupsList);
342
-				$newValue = json_encode($excludedGroups);
343
-				$config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
344
-			}
345
-			$usersGroups = $groupManager->getUserGroupIds($user);
346
-			if (!empty($usersGroups)) {
347
-				$remainingGroups = array_diff($usersGroups, $excludedGroups);
348
-				// if the user is only in groups which are disabled for sharing then
349
-				// sharing is also disabled for the user
350
-				if (empty($remainingGroups)) {
351
-					return true;
352
-				}
353
-			}
354
-		}
355
-		return false;
356
-	}
357
-
358
-	/**
359
-	 * check if share API enforces a default expire date
360
-	 *
361
-	 * @return boolean
362
-	 * @suppress PhanDeprecatedFunction
363
-	 */
364
-	public static function isDefaultExpireDateEnforced() {
365
-		$isDefaultExpireDateEnabled = \OC::$server->getConfig()->getAppValue('core', 'shareapi_default_expire_date', 'no');
366
-		$enforceDefaultExpireDate = false;
367
-		if ($isDefaultExpireDateEnabled === 'yes') {
368
-			$value = \OC::$server->getConfig()->getAppValue('core', 'shareapi_enforce_expire_date', 'no');
369
-			$enforceDefaultExpireDate = $value === 'yes';
370
-		}
371
-
372
-		return $enforceDefaultExpireDate;
373
-	}
374
-
375
-	/**
376
-	 * Get the quota of a user
377
-	 *
378
-	 * @param string $userId
379
-	 * @return float Quota bytes
380
-	 */
381
-	public static function getUserQuota($userId) {
382
-		$user = \OC::$server->getUserManager()->get($userId);
383
-		if (is_null($user)) {
384
-			return \OCP\Files\FileInfo::SPACE_UNLIMITED;
385
-		}
386
-		$userQuota = $user->getQuota();
387
-		if($userQuota === 'none') {
388
-			return \OCP\Files\FileInfo::SPACE_UNLIMITED;
389
-		}
390
-		return OC_Helper::computerFileSize($userQuota);
391
-	}
392
-
393
-	/**
394
-	 * copies the skeleton to the users /files
395
-	 *
396
-	 * @param string $userId
397
-	 * @param \OCP\Files\Folder $userDirectory
398
-	 * @throws \OCP\Files\NotFoundException
399
-	 * @throws \OCP\Files\NotPermittedException
400
-	 * @suppress PhanDeprecatedFunction
401
-	 */
402
-	public static function copySkeleton($userId, \OCP\Files\Folder $userDirectory) {
403
-
404
-		$plainSkeletonDirectory = \OC::$server->getConfig()->getSystemValue('skeletondirectory', \OC::$SERVERROOT . '/core/skeleton');
405
-		$userLang = \OC::$server->getL10NFactory()->findLanguage();
406
-		$skeletonDirectory = str_replace('{lang}', $userLang, $plainSkeletonDirectory);
407
-
408
-		if (!file_exists($skeletonDirectory)) {
409
-			$dialectStart = strpos($userLang, '_');
410
-			if ($dialectStart !== false) {
411
-				$skeletonDirectory = str_replace('{lang}', substr($userLang, 0, $dialectStart), $plainSkeletonDirectory);
412
-			}
413
-			if ($dialectStart === false || !file_exists($skeletonDirectory)) {
414
-				$skeletonDirectory = str_replace('{lang}', 'default', $plainSkeletonDirectory);
415
-			}
416
-			if (!file_exists($skeletonDirectory)) {
417
-				$skeletonDirectory = '';
418
-			}
419
-		}
420
-
421
-		$instanceId = \OC::$server->getConfig()->getSystemValue('instanceid', '');
422
-
423
-		if ($instanceId === null) {
424
-			throw new \RuntimeException('no instance id!');
425
-		}
426
-		$appdata = 'appdata_' . $instanceId;
427
-		if ($userId === $appdata) {
428
-			throw new \RuntimeException('username is reserved name: ' . $appdata);
429
-		}
430
-
431
-		if (!empty($skeletonDirectory)) {
432
-			\OCP\Util::writeLog(
433
-				'files_skeleton',
434
-				'copying skeleton for '.$userId.' from '.$skeletonDirectory.' to '.$userDirectory->getFullPath('/'),
435
-				ILogger::DEBUG
436
-			);
437
-			self::copyr($skeletonDirectory, $userDirectory);
438
-			// update the file cache
439
-			$userDirectory->getStorage()->getScanner()->scan('', \OC\Files\Cache\Scanner::SCAN_RECURSIVE);
440
-		}
441
-	}
442
-
443
-	/**
444
-	 * copies a directory recursively by using streams
445
-	 *
446
-	 * @param string $source
447
-	 * @param \OCP\Files\Folder $target
448
-	 * @return void
449
-	 */
450
-	public static function copyr($source, \OCP\Files\Folder $target) {
451
-		$logger = \OC::$server->getLogger();
452
-
453
-		// Verify if folder exists
454
-		$dir = opendir($source);
455
-		if($dir === false) {
456
-			$logger->error(sprintf('Could not opendir "%s"', $source), ['app' => 'core']);
457
-			return;
458
-		}
459
-
460
-		// Copy the files
461
-		while (false !== ($file = readdir($dir))) {
462
-			if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
463
-				if (is_dir($source . '/' . $file)) {
464
-					$child = $target->newFolder($file);
465
-					self::copyr($source . '/' . $file, $child);
466
-				} else {
467
-					$child = $target->newFile($file);
468
-					$sourceStream = fopen($source . '/' . $file, 'r');
469
-					if($sourceStream === false) {
470
-						$logger->error(sprintf('Could not fopen "%s"', $source . '/' . $file), ['app' => 'core']);
471
-						closedir($dir);
472
-						return;
473
-					}
474
-					stream_copy_to_stream($sourceStream, $child->fopen('w'));
475
-				}
476
-			}
477
-		}
478
-		closedir($dir);
479
-	}
480
-
481
-	/**
482
-	 * @return void
483
-	 * @suppress PhanUndeclaredMethod
484
-	 */
485
-	public static function tearDownFS() {
486
-		\OC\Files\Filesystem::tearDown();
487
-		\OC::$server->getRootFolder()->clearCache();
488
-		self::$fsSetup = false;
489
-		self::$rootMounted = false;
490
-	}
491
-
492
-	/**
493
-	 * get the current installed version of ownCloud
494
-	 *
495
-	 * @return array
496
-	 */
497
-	public static function getVersion() {
498
-		OC_Util::loadVersion();
499
-		return self::$versionCache['OC_Version'];
500
-	}
501
-
502
-	/**
503
-	 * get the current installed version string of ownCloud
504
-	 *
505
-	 * @return string
506
-	 */
507
-	public static function getVersionString() {
508
-		OC_Util::loadVersion();
509
-		return self::$versionCache['OC_VersionString'];
510
-	}
511
-
512
-	/**
513
-	 * @deprecated the value is of no use anymore
514
-	 * @return string
515
-	 */
516
-	public static function getEditionString() {
517
-		return '';
518
-	}
519
-
520
-	/**
521
-	 * @description get the update channel of the current installed of ownCloud.
522
-	 * @return string
523
-	 */
524
-	public static function getChannel() {
525
-		OC_Util::loadVersion();
526
-		return \OC::$server->getConfig()->getSystemValue('updater.release.channel', self::$versionCache['OC_Channel']);
527
-	}
528
-
529
-	/**
530
-	 * @description get the build number of the current installed of ownCloud.
531
-	 * @return string
532
-	 */
533
-	public static function getBuild() {
534
-		OC_Util::loadVersion();
535
-		return self::$versionCache['OC_Build'];
536
-	}
537
-
538
-	/**
539
-	 * @description load the version.php into the session as cache
540
-	 * @suppress PhanUndeclaredVariable
541
-	 */
542
-	private static function loadVersion() {
543
-		if (self::$versionCache !== null) {
544
-			return;
545
-		}
546
-
547
-		$timestamp = filemtime(OC::$SERVERROOT . '/version.php');
548
-		require OC::$SERVERROOT . '/version.php';
549
-		/** @var $timestamp int */
550
-		self::$versionCache['OC_Version_Timestamp'] = $timestamp;
551
-		/** @var $OC_Version string */
552
-		self::$versionCache['OC_Version'] = $OC_Version;
553
-		/** @var $OC_VersionString string */
554
-		self::$versionCache['OC_VersionString'] = $OC_VersionString;
555
-		/** @var $OC_Build string */
556
-		self::$versionCache['OC_Build'] = $OC_Build;
557
-
558
-		/** @var $OC_Channel string */
559
-		self::$versionCache['OC_Channel'] = $OC_Channel;
560
-	}
561
-
562
-	/**
563
-	 * generates a path for JS/CSS files. If no application is provided it will create the path for core.
564
-	 *
565
-	 * @param string $application application to get the files from
566
-	 * @param string $directory directory within this application (css, js, vendor, etc)
567
-	 * @param string $file the file inside of the above folder
568
-	 * @return string the path
569
-	 */
570
-	private static function generatePath($application, $directory, $file) {
571
-		if (is_null($file)) {
572
-			$file = $application;
573
-			$application = "";
574
-		}
575
-		if (!empty($application)) {
576
-			return "$application/$directory/$file";
577
-		} else {
578
-			return "$directory/$file";
579
-		}
580
-	}
581
-
582
-	/**
583
-	 * add a javascript file
584
-	 *
585
-	 * @param string $application application id
586
-	 * @param string|null $file filename
587
-	 * @param bool $prepend prepend the Script to the beginning of the list
588
-	 * @return void
589
-	 */
590
-	public static function addScript($application, $file = null, $prepend = false) {
591
-		$path = OC_Util::generatePath($application, 'js', $file);
592
-
593
-		// core js files need separate handling
594
-		if ($application !== 'core' && $file !== null) {
595
-			self::addTranslations ( $application );
596
-		}
597
-		self::addExternalResource($application, $prepend, $path, "script");
598
-	}
599
-
600
-	/**
601
-	 * add a javascript file from the vendor sub folder
602
-	 *
603
-	 * @param string $application application id
604
-	 * @param string|null $file filename
605
-	 * @param bool $prepend prepend the Script to the beginning of the list
606
-	 * @return void
607
-	 */
608
-	public static function addVendorScript($application, $file = null, $prepend = false) {
609
-		$path = OC_Util::generatePath($application, 'vendor', $file);
610
-		self::addExternalResource($application, $prepend, $path, "script");
611
-	}
612
-
613
-	/**
614
-	 * add a translation JS file
615
-	 *
616
-	 * @param string $application application id
617
-	 * @param string|null $languageCode language code, defaults to the current language
618
-	 * @param bool|null $prepend prepend the Script to the beginning of the list
619
-	 */
620
-	public static function addTranslations($application, $languageCode = null, $prepend = false) {
621
-		if (is_null($languageCode)) {
622
-			$languageCode = \OC::$server->getL10NFactory()->findLanguage($application);
623
-		}
624
-		if (!empty($application)) {
625
-			$path = "$application/l10n/$languageCode";
626
-		} else {
627
-			$path = "l10n/$languageCode";
628
-		}
629
-		self::addExternalResource($application, $prepend, $path, "script");
630
-	}
631
-
632
-	/**
633
-	 * add a css file
634
-	 *
635
-	 * @param string $application application id
636
-	 * @param string|null $file filename
637
-	 * @param bool $prepend prepend the Style to the beginning of the list
638
-	 * @return void
639
-	 */
640
-	public static function addStyle($application, $file = null, $prepend = false) {
641
-		$path = OC_Util::generatePath($application, 'css', $file);
642
-		self::addExternalResource($application, $prepend, $path, "style");
643
-	}
644
-
645
-	/**
646
-	 * add a css file from the vendor sub folder
647
-	 *
648
-	 * @param string $application application id
649
-	 * @param string|null $file filename
650
-	 * @param bool $prepend prepend the Style to the beginning of the list
651
-	 * @return void
652
-	 */
653
-	public static function addVendorStyle($application, $file = null, $prepend = false) {
654
-		$path = OC_Util::generatePath($application, 'vendor', $file);
655
-		self::addExternalResource($application, $prepend, $path, "style");
656
-	}
657
-
658
-	/**
659
-	 * add an external resource css/js file
660
-	 *
661
-	 * @param string $application application id
662
-	 * @param bool $prepend prepend the file to the beginning of the list
663
-	 * @param string $path
664
-	 * @param string $type (script or style)
665
-	 * @return void
666
-	 */
667
-	private static function addExternalResource($application, $prepend, $path, $type = "script") {
668
-
669
-		if ($type === "style") {
670
-			if (!in_array($path, self::$styles)) {
671
-				if ($prepend === true) {
672
-					array_unshift ( self::$styles, $path );
673
-				} else {
674
-					self::$styles[] = $path;
675
-				}
676
-			}
677
-		} elseif ($type === "script") {
678
-			if (!in_array($path, self::$scripts)) {
679
-				if ($prepend === true) {
680
-					array_unshift ( self::$scripts, $path );
681
-				} else {
682
-					self::$scripts [] = $path;
683
-				}
684
-			}
685
-		}
686
-	}
687
-
688
-	/**
689
-	 * Add a custom element to the header
690
-	 * If $text is null then the element will be written as empty element.
691
-	 * So use "" to get a closing tag.
692
-	 * @param string $tag tag name of the element
693
-	 * @param array $attributes array of attributes for the element
694
-	 * @param string $text the text content for the element
695
-	 * @param bool $prepend prepend the header to the beginning of the list
696
-	 */
697
-	public static function addHeader($tag, $attributes, $text = null, $prepend = false) {
698
-		$header = [
699
-			'tag' => $tag,
700
-			'attributes' => $attributes,
701
-			'text' => $text
702
-		];
703
-		if ($prepend === true) {
704
-			array_unshift (self::$headers, $header);
705
-
706
-		} else {
707
-			self::$headers[] = $header;
708
-		}
709
-	}
710
-
711
-	/**
712
-	 * check if the current server configuration is suitable for ownCloud
713
-	 *
714
-	 * @param \OC\SystemConfig $config
715
-	 * @return array arrays with error messages and hints
716
-	 */
717
-	public static function checkServer(\OC\SystemConfig $config) {
718
-		$l = \OC::$server->getL10N('lib');
719
-		$errors = [];
720
-		$CONFIG_DATADIRECTORY = $config->getValue('datadirectory', OC::$SERVERROOT . '/data');
721
-
722
-		if (!self::needUpgrade($config) && $config->getValue('installed', false)) {
723
-			// this check needs to be done every time
724
-			$errors = self::checkDataDirectoryValidity($CONFIG_DATADIRECTORY);
725
-		}
726
-
727
-		// Assume that if checkServer() succeeded before in this session, then all is fine.
728
-		if (\OC::$server->getSession()->exists('checkServer_succeeded') && \OC::$server->getSession()->get('checkServer_succeeded')) {
729
-			return $errors;
730
-		}
731
-
732
-		$webServerRestart = false;
733
-		$setup = new \OC\Setup(
734
-			$config,
735
-			\OC::$server->getIniWrapper(),
736
-			\OC::$server->getL10N('lib'),
737
-			\OC::$server->query(\OCP\Defaults::class),
738
-			\OC::$server->getLogger(),
739
-			\OC::$server->getSecureRandom(),
740
-			\OC::$server->query(\OC\Installer::class)
741
-		);
742
-
743
-		$urlGenerator = \OC::$server->getURLGenerator();
744
-
745
-		$availableDatabases = $setup->getSupportedDatabases();
746
-		if (empty($availableDatabases)) {
747
-			$errors[] = [
748
-				'error' => $l->t('No database drivers (sqlite, mysql, or postgresql) installed.'),
749
-				'hint' => '' //TODO: sane hint
750
-			];
751
-			$webServerRestart = true;
752
-		}
753
-
754
-		// Check if config folder is writable.
755
-		if(!OC_Helper::isReadOnlyConfigEnabled()) {
756
-			if (!is_writable(OC::$configDir) or !is_readable(OC::$configDir)) {
757
-				$errors[] = [
758
-					'error' => $l->t('Cannot write into "config" directory'),
759
-					'hint' => $l->t('This can usually be fixed by giving the webserver write access to the config directory. See %s',
760
-						[ $urlGenerator->linkToDocs('admin-dir_permissions') ]) . '. '
761
-						. $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it. See %s',
762
-						[ $urlGenerator->linkToDocs('admin-config') ] )
763
-				];
764
-			}
765
-		}
766
-
767
-		// Check if there is a writable install folder.
768
-		if ($config->getValue('appstoreenabled', true)) {
769
-			if (OC_App::getInstallPath() === null
770
-				|| !is_writable(OC_App::getInstallPath())
771
-				|| !is_readable(OC_App::getInstallPath())
772
-			) {
773
-				$errors[] = [
774
-					'error' => $l->t('Cannot write into "apps" directory'),
775
-					'hint' => $l->t('This can usually be fixed by giving the webserver write access to the apps directory'
776
-						. ' or disabling the appstore in the config file. See %s',
777
-						[$urlGenerator->linkToDocs('admin-dir_permissions')])
778
-				];
779
-			}
780
-		}
781
-		// Create root dir.
782
-		if ($config->getValue('installed', false)) {
783
-			if (!is_dir($CONFIG_DATADIRECTORY)) {
784
-				$success = @mkdir($CONFIG_DATADIRECTORY);
785
-				if ($success) {
786
-					$errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY));
787
-				} else {
788
-					$errors[] = [
789
-						'error' => $l->t('Cannot create "data" directory'),
790
-						'hint' => $l->t('This can usually be fixed by giving the webserver write access to the root directory. See %s',
791
-							[$urlGenerator->linkToDocs('admin-dir_permissions')])
792
-					];
793
-				}
794
-			} else if (!is_writable($CONFIG_DATADIRECTORY) or !is_readable($CONFIG_DATADIRECTORY)) {
795
-				// is_writable doesn't work for NFS mounts, so try to write a file and check if it exists.
796
-				$testFile = sprintf('%s/%s.tmp', $CONFIG_DATADIRECTORY, uniqid('data_dir_writability_test_'));
797
-				$handle = fopen($testFile, 'w');
798
-				if (!$handle || fwrite($handle, 'Test write operation') === false) {
799
-					$permissionsHint = $l->t('Permissions can usually be fixed by giving the webserver write access to the root directory. See %s.',
800
-						[$urlGenerator->linkToDocs('admin-dir_permissions')]);
801
-					$errors[] = [
802
-						'error' => 'Your data directory is not writable',
803
-						'hint' => $permissionsHint
804
-					];
805
-				} else {
806
-					fclose($handle);
807
-					unlink($testFile);
808
-				}
809
-			} else {
810
-				$errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY));
811
-			}
812
-		}
813
-
814
-		if (!OC_Util::isSetLocaleWorking()) {
815
-			$errors[] = [
816
-				'error' => $l->t('Setting locale to %s failed',
817
-					['en_US.UTF-8/fr_FR.UTF-8/es_ES.UTF-8/de_DE.UTF-8/ru_RU.UTF-8/'
818
-						. 'pt_BR.UTF-8/it_IT.UTF-8/ja_JP.UTF-8/zh_CN.UTF-8']),
819
-				'hint' => $l->t('Please install one of these locales on your system and restart your webserver.')
820
-			];
821
-		}
822
-
823
-		// Contains the dependencies that should be checked against
824
-		// classes = class_exists
825
-		// functions = function_exists
826
-		// defined = defined
827
-		// ini = ini_get
828
-		// If the dependency is not found the missing module name is shown to the EndUser
829
-		// When adding new checks always verify that they pass on Travis as well
830
-		// for ini settings, see https://github.com/owncloud/administration/blob/master/travis-ci/custom.ini
831
-		$dependencies = [
832
-			'classes' => [
833
-				'ZipArchive' => 'zip',
834
-				'DOMDocument' => 'dom',
835
-				'XMLWriter' => 'XMLWriter',
836
-				'XMLReader' => 'XMLReader',
837
-			],
838
-			'functions' => [
839
-				'xml_parser_create' => 'libxml',
840
-				'mb_strcut' => 'mbstring',
841
-				'ctype_digit' => 'ctype',
842
-				'json_encode' => 'JSON',
843
-				'gd_info' => 'GD',
844
-				'gzencode' => 'zlib',
845
-				'iconv' => 'iconv',
846
-				'simplexml_load_string' => 'SimpleXML',
847
-				'hash' => 'HASH Message Digest Framework',
848
-				'curl_init' => 'cURL',
849
-				'openssl_verify' => 'OpenSSL',
850
-			],
851
-			'defined' => [
852
-				'PDO::ATTR_DRIVER_NAME' => 'PDO'
853
-			],
854
-			'ini' => [
855
-				'default_charset' => 'UTF-8',
856
-			],
857
-		];
858
-		$missingDependencies = [];
859
-		$invalidIniSettings = [];
860
-		$moduleHint = $l->t('Please ask your server administrator to install the module.');
861
-
862
-		$iniWrapper = \OC::$server->getIniWrapper();
863
-		foreach ($dependencies['classes'] as $class => $module) {
864
-			if (!class_exists($class)) {
865
-				$missingDependencies[] = $module;
866
-			}
867
-		}
868
-		foreach ($dependencies['functions'] as $function => $module) {
869
-			if (!function_exists($function)) {
870
-				$missingDependencies[] = $module;
871
-			}
872
-		}
873
-		foreach ($dependencies['defined'] as $defined => $module) {
874
-			if (!defined($defined)) {
875
-				$missingDependencies[] = $module;
876
-			}
877
-		}
878
-		foreach ($dependencies['ini'] as $setting => $expected) {
879
-			if (is_bool($expected)) {
880
-				if ($iniWrapper->getBool($setting) !== $expected) {
881
-					$invalidIniSettings[] = [$setting, $expected];
882
-				}
883
-			}
884
-			if (is_int($expected)) {
885
-				if ($iniWrapper->getNumeric($setting) !== $expected) {
886
-					$invalidIniSettings[] = [$setting, $expected];
887
-				}
888
-			}
889
-			if (is_string($expected)) {
890
-				if (strtolower($iniWrapper->getString($setting)) !== strtolower($expected)) {
891
-					$invalidIniSettings[] = [$setting, $expected];
892
-				}
893
-			}
894
-		}
895
-
896
-		foreach($missingDependencies as $missingDependency) {
897
-			$errors[] = [
898
-				'error' => $l->t('PHP module %s not installed.', [$missingDependency]),
899
-				'hint' => $moduleHint
900
-			];
901
-			$webServerRestart = true;
902
-		}
903
-		foreach($invalidIniSettings as $setting) {
904
-			if(is_bool($setting[1])) {
905
-				$setting[1] = $setting[1] ? 'on' : 'off';
906
-			}
907
-			$errors[] = [
908
-				'error' => $l->t('PHP setting "%s" is not set to "%s".', [$setting[0], var_export($setting[1], true)]),
909
-				'hint' =>  $l->t('Adjusting this setting in php.ini will make Nextcloud run again')
910
-			];
911
-			$webServerRestart = true;
912
-		}
913
-
914
-		/**
915
-		 * The mbstring.func_overload check can only be performed if the mbstring
916
-		 * module is installed as it will return null if the checking setting is
917
-		 * not available and thus a check on the boolean value fails.
918
-		 *
919
-		 * TODO: Should probably be implemented in the above generic dependency
920
-		 *       check somehow in the long-term.
921
-		 */
922
-		if($iniWrapper->getBool('mbstring.func_overload') !== null &&
923
-			$iniWrapper->getBool('mbstring.func_overload') === true) {
924
-			$errors[] = [
925
-				'error' => $l->t('mbstring.func_overload is set to "%s" instead of the expected value "0"', [$iniWrapper->getString('mbstring.func_overload')]),
926
-				'hint' => $l->t('To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini')
927
-			];
928
-		}
929
-
930
-		if(function_exists('xml_parser_create') &&
931
-			LIBXML_LOADED_VERSION < 20700 ) {
932
-			$version = LIBXML_LOADED_VERSION;
933
-			$major = floor($version/10000);
934
-			$version -= ($major * 10000);
935
-			$minor = floor($version/100);
936
-			$version -= ($minor * 100);
937
-			$patch = $version;
938
-			$errors[] = [
939
-				'error' => $l->t('libxml2 2.7.0 is at least required. Currently %s is installed.', [$major . '.' . $minor . '.' . $patch]),
940
-				'hint' => $l->t('To fix this issue update your libxml2 version and restart your web server.')
941
-			];
942
-		}
943
-
944
-		if (!self::isAnnotationsWorking()) {
945
-			$errors[] = [
946
-				'error' => $l->t('PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible.'),
947
-				'hint' => $l->t('This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator.')
948
-			];
949
-		}
950
-
951
-		if (!\OC::$CLI && $webServerRestart) {
952
-			$errors[] = [
953
-				'error' => $l->t('PHP modules have been installed, but they are still listed as missing?'),
954
-				'hint' => $l->t('Please ask your server administrator to restart the web server.')
955
-			];
956
-		}
957
-
958
-		$errors = array_merge($errors, self::checkDatabaseVersion());
959
-
960
-		// Cache the result of this function
961
-		\OC::$server->getSession()->set('checkServer_succeeded', count($errors) == 0);
962
-
963
-		return $errors;
964
-	}
965
-
966
-	/**
967
-	 * Check the database version
968
-	 *
969
-	 * @return array errors array
970
-	 */
971
-	public static function checkDatabaseVersion() {
972
-		$l = \OC::$server->getL10N('lib');
973
-		$errors = [];
974
-		$dbType = \OC::$server->getSystemConfig()->getValue('dbtype', 'sqlite');
975
-		if ($dbType === 'pgsql') {
976
-			// check PostgreSQL version
977
-			try {
978
-				$result = \OC_DB::executeAudited('SHOW SERVER_VERSION');
979
-				$data = $result->fetchRow();
980
-				if (isset($data['server_version'])) {
981
-					$version = $data['server_version'];
982
-					if (version_compare($version, '9.0.0', '<')) {
983
-						$errors[] = [
984
-							'error' => $l->t('PostgreSQL >= 9 required'),
985
-							'hint' => $l->t('Please upgrade your database version')
986
-						];
987
-					}
988
-				}
989
-			} catch (\Doctrine\DBAL\DBALException $e) {
990
-				$logger = \OC::$server->getLogger();
991
-				$logger->warning('Error occurred while checking PostgreSQL version, assuming >= 9');
992
-				$logger->logException($e);
993
-			}
994
-		}
995
-		return $errors;
996
-	}
997
-
998
-	/**
999
-	 * Check for correct file permissions of data directory
1000
-	 *
1001
-	 * @param string $dataDirectory
1002
-	 * @return array arrays with error messages and hints
1003
-	 */
1004
-	public static function checkDataDirectoryPermissions($dataDirectory) {
1005
-		if(\OC::$server->getConfig()->getSystemValue('check_data_directory_permissions', true) === false) {
1006
-			return  [];
1007
-		}
1008
-		$l = \OC::$server->getL10N('lib');
1009
-		$errors = [];
1010
-		$permissionsModHint = $l->t('Please change the permissions to 0770 so that the directory'
1011
-			. ' cannot be listed by other users.');
1012
-		$perms = substr(decoct(@fileperms($dataDirectory)), -3);
1013
-		if (substr($perms, -1) !== '0') {
1014
-			chmod($dataDirectory, 0770);
1015
-			clearstatcache();
1016
-			$perms = substr(decoct(@fileperms($dataDirectory)), -3);
1017
-			if ($perms[2] !== '0') {
1018
-				$errors[] = [
1019
-					'error' => $l->t('Your data directory is readable by other users'),
1020
-					'hint' => $permissionsModHint
1021
-				];
1022
-			}
1023
-		}
1024
-		return $errors;
1025
-	}
1026
-
1027
-	/**
1028
-	 * Check that the data directory exists and is valid by
1029
-	 * checking the existence of the ".ocdata" file.
1030
-	 *
1031
-	 * @param string $dataDirectory data directory path
1032
-	 * @return array errors found
1033
-	 */
1034
-	public static function checkDataDirectoryValidity($dataDirectory) {
1035
-		$l = \OC::$server->getL10N('lib');
1036
-		$errors = [];
1037
-		if ($dataDirectory[0] !== '/') {
1038
-			$errors[] = [
1039
-				'error' => $l->t('Your data directory must be an absolute path'),
1040
-				'hint' => $l->t('Check the value of "datadirectory" in your configuration')
1041
-			];
1042
-		}
1043
-		if (!file_exists($dataDirectory . '/.ocdata')) {
1044
-			$errors[] = [
1045
-				'error' => $l->t('Your data directory is invalid'),
1046
-				'hint' => $l->t('Ensure there is a file called ".ocdata"' .
1047
-					' in the root of the data directory.')
1048
-			];
1049
-		}
1050
-		return $errors;
1051
-	}
1052
-
1053
-	/**
1054
-	 * Check if the user is logged in, redirects to home if not. With
1055
-	 * redirect URL parameter to the request URI.
1056
-	 *
1057
-	 * @return void
1058
-	 */
1059
-	public static function checkLoggedIn() {
1060
-		// Check if we are a user
1061
-		if (!\OC::$server->getUserSession()->isLoggedIn()) {
1062
-			header('Location: ' . \OC::$server->getURLGenerator()->linkToRoute(
1063
-						'core.login.showLoginForm',
1064
-						[
1065
-							'redirect_url' => \OC::$server->getRequest()->getRequestUri(),
1066
-						]
1067
-					)
1068
-			);
1069
-			exit();
1070
-		}
1071
-		// Redirect to 2FA challenge selection if 2FA challenge was not solved yet
1072
-		if (\OC::$server->getTwoFactorAuthManager()->needsSecondFactor(\OC::$server->getUserSession()->getUser())) {
1073
-			header('Location: ' . \OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.selectChallenge'));
1074
-			exit();
1075
-		}
1076
-	}
1077
-
1078
-	/**
1079
-	 * Check if the user is a admin, redirects to home if not
1080
-	 *
1081
-	 * @return void
1082
-	 */
1083
-	public static function checkAdminUser() {
1084
-		OC_Util::checkLoggedIn();
1085
-		if (!OC_User::isAdminUser(OC_User::getUser())) {
1086
-			header('Location: ' . \OCP\Util::linkToAbsolute('', 'index.php'));
1087
-			exit();
1088
-		}
1089
-	}
1090
-
1091
-	/**
1092
-	 * Returns the URL of the default page
1093
-	 * based on the system configuration and
1094
-	 * the apps visible for the current user
1095
-	 *
1096
-	 * @return string URL
1097
-	 * @suppress PhanDeprecatedFunction
1098
-	 */
1099
-	public static function getDefaultPageUrl() {
1100
-		$urlGenerator = \OC::$server->getURLGenerator();
1101
-		// Deny the redirect if the URL contains a @
1102
-		// This prevents unvalidated redirects like ?redirect_url=:[email protected]
1103
-		if (isset($_REQUEST['redirect_url']) && strpos($_REQUEST['redirect_url'], '@') === false) {
1104
-			$location = $urlGenerator->getAbsoluteURL(urldecode($_REQUEST['redirect_url']));
1105
-		} else {
1106
-			$defaultPage = \OC::$server->getConfig()->getAppValue('core', 'defaultpage');
1107
-			if ($defaultPage) {
1108
-				$location = $urlGenerator->getAbsoluteURL($defaultPage);
1109
-			} else {
1110
-				$appId = 'files';
1111
-				$config = \OC::$server->getConfig();
1112
-				$defaultApps = explode(',', $config->getSystemValue('defaultapp', 'files'));
1113
-				// find the first app that is enabled for the current user
1114
-				foreach ($defaultApps as $defaultApp) {
1115
-					$defaultApp = OC_App::cleanAppId(strip_tags($defaultApp));
1116
-					if (static::getAppManager()->isEnabledForUser($defaultApp)) {
1117
-						$appId = $defaultApp;
1118
-						break;
1119
-					}
1120
-				}
1121
-
1122
-				if($config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true') {
1123
-					$location = $urlGenerator->getAbsoluteURL('/apps/' . $appId . '/');
1124
-				} else {
1125
-					$location = $urlGenerator->getAbsoluteURL('/index.php/apps/' . $appId . '/');
1126
-				}
1127
-			}
1128
-		}
1129
-		return $location;
1130
-	}
1131
-
1132
-	/**
1133
-	 * Redirect to the user default page
1134
-	 *
1135
-	 * @return void
1136
-	 */
1137
-	public static function redirectToDefaultPage() {
1138
-		$location = self::getDefaultPageUrl();
1139
-		header('Location: ' . $location);
1140
-		exit();
1141
-	}
1142
-
1143
-	/**
1144
-	 * get an id unique for this instance
1145
-	 *
1146
-	 * @return string
1147
-	 */
1148
-	public static function getInstanceId() {
1149
-		$id = \OC::$server->getSystemConfig()->getValue('instanceid', null);
1150
-		if (is_null($id)) {
1151
-			// We need to guarantee at least one letter in instanceid so it can be used as the session_name
1152
-			$id = 'oc' . \OC::$server->getSecureRandom()->generate(10, \OCP\Security\ISecureRandom::CHAR_LOWER.\OCP\Security\ISecureRandom::CHAR_DIGITS);
1153
-			\OC::$server->getSystemConfig()->setValue('instanceid', $id);
1154
-		}
1155
-		return $id;
1156
-	}
1157
-
1158
-	/**
1159
-	 * Public function to sanitize HTML
1160
-	 *
1161
-	 * This function is used to sanitize HTML and should be applied on any
1162
-	 * string or array of strings before displaying it on a web page.
1163
-	 *
1164
-	 * @param string|array $value
1165
-	 * @return string|array an array of sanitized strings or a single sanitized string, depends on the input parameter.
1166
-	 */
1167
-	public static function sanitizeHTML($value) {
1168
-		if (is_array($value)) {
1169
-			$value = array_map(function($value) {
1170
-				return self::sanitizeHTML($value);
1171
-			}, $value);
1172
-		} else {
1173
-			// Specify encoding for PHP<5.4
1174
-			$value = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
1175
-		}
1176
-		return $value;
1177
-	}
1178
-
1179
-	/**
1180
-	 * Public function to encode url parameters
1181
-	 *
1182
-	 * This function is used to encode path to file before output.
1183
-	 * Encoding is done according to RFC 3986 with one exception:
1184
-	 * Character '/' is preserved as is.
1185
-	 *
1186
-	 * @param string $component part of URI to encode
1187
-	 * @return string
1188
-	 */
1189
-	public static function encodePath($component) {
1190
-		$encoded = rawurlencode($component);
1191
-		$encoded = str_replace('%2F', '/', $encoded);
1192
-		return $encoded;
1193
-	}
1194
-
1195
-
1196
-	public function createHtaccessTestFile(\OCP\IConfig $config) {
1197
-		// php dev server does not support htaccess
1198
-		if (php_sapi_name() === 'cli-server') {
1199
-			return false;
1200
-		}
1201
-
1202
-		// testdata
1203
-		$fileName = '/htaccesstest.txt';
1204
-		$testContent = 'This is used for testing whether htaccess is properly enabled to disallow access from the outside. This file can be safely removed.';
1205
-
1206
-		// creating a test file
1207
-		$testFile = $config->getSystemValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $fileName;
1208
-
1209
-		if (file_exists($testFile)) {// already running this test, possible recursive call
1210
-			return false;
1211
-		}
1212
-
1213
-		$fp = @fopen($testFile, 'w');
1214
-		if (!$fp) {
1215
-			throw new OC\HintException('Can\'t create test file to check for working .htaccess file.',
1216
-				'Make sure it is possible for the webserver to write to ' . $testFile);
1217
-		}
1218
-		fwrite($fp, $testContent);
1219
-		fclose($fp);
1220
-
1221
-		return $testContent;
1222
-	}
1223
-
1224
-	/**
1225
-	 * Check if the .htaccess file is working
1226
-	 * @param \OCP\IConfig $config
1227
-	 * @return bool
1228
-	 * @throws Exception
1229
-	 * @throws \OC\HintException If the test file can't get written.
1230
-	 */
1231
-	public function isHtaccessWorking(\OCP\IConfig $config) {
1232
-
1233
-		if (\OC::$CLI || !$config->getSystemValue('check_for_working_htaccess', true)) {
1234
-			return true;
1235
-		}
1236
-
1237
-		$testContent = $this->createHtaccessTestFile($config);
1238
-		if ($testContent === false) {
1239
-			return false;
1240
-		}
1241
-
1242
-		$fileName = '/htaccesstest.txt';
1243
-		$testFile = $config->getSystemValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $fileName;
1244
-
1245
-		// accessing the file via http
1246
-		$url = \OC::$server->getURLGenerator()->getAbsoluteURL(OC::$WEBROOT . '/data' . $fileName);
1247
-		try {
1248
-			$content = \OC::$server->getHTTPClientService()->newClient()->get($url)->getBody();
1249
-		} catch (\Exception $e) {
1250
-			$content = false;
1251
-		}
1252
-
1253
-		if (strpos($url, 'https:') === 0) {
1254
-			$url = 'http:' . substr($url, 6);
1255
-		} else {
1256
-			$url = 'https:' . substr($url, 5);
1257
-		}
1258
-
1259
-		try {
1260
-			$fallbackContent = \OC::$server->getHTTPClientService()->newClient()->get($url)->getBody();
1261
-		} catch (\Exception $e) {
1262
-			$fallbackContent = false;
1263
-		}
1264
-
1265
-		// cleanup
1266
-		@unlink($testFile);
1267
-
1268
-		/*
269
+            if ($mount->getOption('readonly', false)) {
270
+                return new \OC\Files\Storage\Wrapper\PermissionsMask([
271
+                    'storage' => $storage,
272
+                    'mask' => \OCP\Constants::PERMISSION_ALL & ~(
273
+                        \OCP\Constants::PERMISSION_UPDATE |
274
+                        \OCP\Constants::PERMISSION_CREATE |
275
+                        \OCP\Constants::PERMISSION_DELETE
276
+                    ),
277
+                ]);
278
+            }
279
+            return $storage;
280
+        });
281
+
282
+        OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user]);
283
+
284
+        \OC\Files\Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
285
+
286
+        //check if we are using an object storage
287
+        $objectStore = \OC::$server->getSystemConfig()->getValue('objectstore', null);
288
+        $objectStoreMultibucket = \OC::$server->getSystemConfig()->getValue('objectstore_multibucket', null);
289
+
290
+        // use the same order as in ObjectHomeMountProvider
291
+        if (isset($objectStoreMultibucket)) {
292
+            self::initObjectStoreMultibucketRootFS($objectStoreMultibucket);
293
+        } elseif (isset($objectStore)) {
294
+            self::initObjectStoreRootFS($objectStore);
295
+        } else {
296
+            self::initLocalStorageRootFS();
297
+        }
298
+
299
+        if ($user != '' && !\OC::$server->getUserManager()->userExists($user)) {
300
+            \OC::$server->getEventLogger()->end('setup_fs');
301
+            return false;
302
+        }
303
+
304
+        //if we aren't logged in, there is no use to set up the filesystem
305
+        if ($user != "") {
306
+
307
+            $userDir = '/' . $user . '/files';
308
+
309
+            //jail the user into his "home" directory
310
+            \OC\Files\Filesystem::init($user, $userDir);
311
+
312
+            OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $user, 'user_dir' => $userDir]);
313
+        }
314
+        \OC::$server->getEventLogger()->end('setup_fs');
315
+        return true;
316
+    }
317
+
318
+    /**
319
+     * check if a password is required for each public link
320
+     *
321
+     * @return boolean
322
+     * @suppress PhanDeprecatedFunction
323
+     */
324
+    public static function isPublicLinkPasswordRequired() {
325
+        $enforcePassword = \OC::$server->getConfig()->getAppValue('core', 'shareapi_enforce_links_password', 'no');
326
+        return $enforcePassword === 'yes';
327
+    }
328
+
329
+    /**
330
+     * check if sharing is disabled for the current user
331
+     * @param IConfig $config
332
+     * @param IGroupManager $groupManager
333
+     * @param IUser|null $user
334
+     * @return bool
335
+     */
336
+    public static function isSharingDisabledForUser(IConfig $config, IGroupManager $groupManager, $user) {
337
+        if ($config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
338
+            $groupsList = $config->getAppValue('core', 'shareapi_exclude_groups_list', '');
339
+            $excludedGroups = json_decode($groupsList);
340
+            if (is_null($excludedGroups)) {
341
+                $excludedGroups = explode(',', $groupsList);
342
+                $newValue = json_encode($excludedGroups);
343
+                $config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
344
+            }
345
+            $usersGroups = $groupManager->getUserGroupIds($user);
346
+            if (!empty($usersGroups)) {
347
+                $remainingGroups = array_diff($usersGroups, $excludedGroups);
348
+                // if the user is only in groups which are disabled for sharing then
349
+                // sharing is also disabled for the user
350
+                if (empty($remainingGroups)) {
351
+                    return true;
352
+                }
353
+            }
354
+        }
355
+        return false;
356
+    }
357
+
358
+    /**
359
+     * check if share API enforces a default expire date
360
+     *
361
+     * @return boolean
362
+     * @suppress PhanDeprecatedFunction
363
+     */
364
+    public static function isDefaultExpireDateEnforced() {
365
+        $isDefaultExpireDateEnabled = \OC::$server->getConfig()->getAppValue('core', 'shareapi_default_expire_date', 'no');
366
+        $enforceDefaultExpireDate = false;
367
+        if ($isDefaultExpireDateEnabled === 'yes') {
368
+            $value = \OC::$server->getConfig()->getAppValue('core', 'shareapi_enforce_expire_date', 'no');
369
+            $enforceDefaultExpireDate = $value === 'yes';
370
+        }
371
+
372
+        return $enforceDefaultExpireDate;
373
+    }
374
+
375
+    /**
376
+     * Get the quota of a user
377
+     *
378
+     * @param string $userId
379
+     * @return float Quota bytes
380
+     */
381
+    public static function getUserQuota($userId) {
382
+        $user = \OC::$server->getUserManager()->get($userId);
383
+        if (is_null($user)) {
384
+            return \OCP\Files\FileInfo::SPACE_UNLIMITED;
385
+        }
386
+        $userQuota = $user->getQuota();
387
+        if($userQuota === 'none') {
388
+            return \OCP\Files\FileInfo::SPACE_UNLIMITED;
389
+        }
390
+        return OC_Helper::computerFileSize($userQuota);
391
+    }
392
+
393
+    /**
394
+     * copies the skeleton to the users /files
395
+     *
396
+     * @param string $userId
397
+     * @param \OCP\Files\Folder $userDirectory
398
+     * @throws \OCP\Files\NotFoundException
399
+     * @throws \OCP\Files\NotPermittedException
400
+     * @suppress PhanDeprecatedFunction
401
+     */
402
+    public static function copySkeleton($userId, \OCP\Files\Folder $userDirectory) {
403
+
404
+        $plainSkeletonDirectory = \OC::$server->getConfig()->getSystemValue('skeletondirectory', \OC::$SERVERROOT . '/core/skeleton');
405
+        $userLang = \OC::$server->getL10NFactory()->findLanguage();
406
+        $skeletonDirectory = str_replace('{lang}', $userLang, $plainSkeletonDirectory);
407
+
408
+        if (!file_exists($skeletonDirectory)) {
409
+            $dialectStart = strpos($userLang, '_');
410
+            if ($dialectStart !== false) {
411
+                $skeletonDirectory = str_replace('{lang}', substr($userLang, 0, $dialectStart), $plainSkeletonDirectory);
412
+            }
413
+            if ($dialectStart === false || !file_exists($skeletonDirectory)) {
414
+                $skeletonDirectory = str_replace('{lang}', 'default', $plainSkeletonDirectory);
415
+            }
416
+            if (!file_exists($skeletonDirectory)) {
417
+                $skeletonDirectory = '';
418
+            }
419
+        }
420
+
421
+        $instanceId = \OC::$server->getConfig()->getSystemValue('instanceid', '');
422
+
423
+        if ($instanceId === null) {
424
+            throw new \RuntimeException('no instance id!');
425
+        }
426
+        $appdata = 'appdata_' . $instanceId;
427
+        if ($userId === $appdata) {
428
+            throw new \RuntimeException('username is reserved name: ' . $appdata);
429
+        }
430
+
431
+        if (!empty($skeletonDirectory)) {
432
+            \OCP\Util::writeLog(
433
+                'files_skeleton',
434
+                'copying skeleton for '.$userId.' from '.$skeletonDirectory.' to '.$userDirectory->getFullPath('/'),
435
+                ILogger::DEBUG
436
+            );
437
+            self::copyr($skeletonDirectory, $userDirectory);
438
+            // update the file cache
439
+            $userDirectory->getStorage()->getScanner()->scan('', \OC\Files\Cache\Scanner::SCAN_RECURSIVE);
440
+        }
441
+    }
442
+
443
+    /**
444
+     * copies a directory recursively by using streams
445
+     *
446
+     * @param string $source
447
+     * @param \OCP\Files\Folder $target
448
+     * @return void
449
+     */
450
+    public static function copyr($source, \OCP\Files\Folder $target) {
451
+        $logger = \OC::$server->getLogger();
452
+
453
+        // Verify if folder exists
454
+        $dir = opendir($source);
455
+        if($dir === false) {
456
+            $logger->error(sprintf('Could not opendir "%s"', $source), ['app' => 'core']);
457
+            return;
458
+        }
459
+
460
+        // Copy the files
461
+        while (false !== ($file = readdir($dir))) {
462
+            if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
463
+                if (is_dir($source . '/' . $file)) {
464
+                    $child = $target->newFolder($file);
465
+                    self::copyr($source . '/' . $file, $child);
466
+                } else {
467
+                    $child = $target->newFile($file);
468
+                    $sourceStream = fopen($source . '/' . $file, 'r');
469
+                    if($sourceStream === false) {
470
+                        $logger->error(sprintf('Could not fopen "%s"', $source . '/' . $file), ['app' => 'core']);
471
+                        closedir($dir);
472
+                        return;
473
+                    }
474
+                    stream_copy_to_stream($sourceStream, $child->fopen('w'));
475
+                }
476
+            }
477
+        }
478
+        closedir($dir);
479
+    }
480
+
481
+    /**
482
+     * @return void
483
+     * @suppress PhanUndeclaredMethod
484
+     */
485
+    public static function tearDownFS() {
486
+        \OC\Files\Filesystem::tearDown();
487
+        \OC::$server->getRootFolder()->clearCache();
488
+        self::$fsSetup = false;
489
+        self::$rootMounted = false;
490
+    }
491
+
492
+    /**
493
+     * get the current installed version of ownCloud
494
+     *
495
+     * @return array
496
+     */
497
+    public static function getVersion() {
498
+        OC_Util::loadVersion();
499
+        return self::$versionCache['OC_Version'];
500
+    }
501
+
502
+    /**
503
+     * get the current installed version string of ownCloud
504
+     *
505
+     * @return string
506
+     */
507
+    public static function getVersionString() {
508
+        OC_Util::loadVersion();
509
+        return self::$versionCache['OC_VersionString'];
510
+    }
511
+
512
+    /**
513
+     * @deprecated the value is of no use anymore
514
+     * @return string
515
+     */
516
+    public static function getEditionString() {
517
+        return '';
518
+    }
519
+
520
+    /**
521
+     * @description get the update channel of the current installed of ownCloud.
522
+     * @return string
523
+     */
524
+    public static function getChannel() {
525
+        OC_Util::loadVersion();
526
+        return \OC::$server->getConfig()->getSystemValue('updater.release.channel', self::$versionCache['OC_Channel']);
527
+    }
528
+
529
+    /**
530
+     * @description get the build number of the current installed of ownCloud.
531
+     * @return string
532
+     */
533
+    public static function getBuild() {
534
+        OC_Util::loadVersion();
535
+        return self::$versionCache['OC_Build'];
536
+    }
537
+
538
+    /**
539
+     * @description load the version.php into the session as cache
540
+     * @suppress PhanUndeclaredVariable
541
+     */
542
+    private static function loadVersion() {
543
+        if (self::$versionCache !== null) {
544
+            return;
545
+        }
546
+
547
+        $timestamp = filemtime(OC::$SERVERROOT . '/version.php');
548
+        require OC::$SERVERROOT . '/version.php';
549
+        /** @var $timestamp int */
550
+        self::$versionCache['OC_Version_Timestamp'] = $timestamp;
551
+        /** @var $OC_Version string */
552
+        self::$versionCache['OC_Version'] = $OC_Version;
553
+        /** @var $OC_VersionString string */
554
+        self::$versionCache['OC_VersionString'] = $OC_VersionString;
555
+        /** @var $OC_Build string */
556
+        self::$versionCache['OC_Build'] = $OC_Build;
557
+
558
+        /** @var $OC_Channel string */
559
+        self::$versionCache['OC_Channel'] = $OC_Channel;
560
+    }
561
+
562
+    /**
563
+     * generates a path for JS/CSS files. If no application is provided it will create the path for core.
564
+     *
565
+     * @param string $application application to get the files from
566
+     * @param string $directory directory within this application (css, js, vendor, etc)
567
+     * @param string $file the file inside of the above folder
568
+     * @return string the path
569
+     */
570
+    private static function generatePath($application, $directory, $file) {
571
+        if (is_null($file)) {
572
+            $file = $application;
573
+            $application = "";
574
+        }
575
+        if (!empty($application)) {
576
+            return "$application/$directory/$file";
577
+        } else {
578
+            return "$directory/$file";
579
+        }
580
+    }
581
+
582
+    /**
583
+     * add a javascript file
584
+     *
585
+     * @param string $application application id
586
+     * @param string|null $file filename
587
+     * @param bool $prepend prepend the Script to the beginning of the list
588
+     * @return void
589
+     */
590
+    public static function addScript($application, $file = null, $prepend = false) {
591
+        $path = OC_Util::generatePath($application, 'js', $file);
592
+
593
+        // core js files need separate handling
594
+        if ($application !== 'core' && $file !== null) {
595
+            self::addTranslations ( $application );
596
+        }
597
+        self::addExternalResource($application, $prepend, $path, "script");
598
+    }
599
+
600
+    /**
601
+     * add a javascript file from the vendor sub folder
602
+     *
603
+     * @param string $application application id
604
+     * @param string|null $file filename
605
+     * @param bool $prepend prepend the Script to the beginning of the list
606
+     * @return void
607
+     */
608
+    public static function addVendorScript($application, $file = null, $prepend = false) {
609
+        $path = OC_Util::generatePath($application, 'vendor', $file);
610
+        self::addExternalResource($application, $prepend, $path, "script");
611
+    }
612
+
613
+    /**
614
+     * add a translation JS file
615
+     *
616
+     * @param string $application application id
617
+     * @param string|null $languageCode language code, defaults to the current language
618
+     * @param bool|null $prepend prepend the Script to the beginning of the list
619
+     */
620
+    public static function addTranslations($application, $languageCode = null, $prepend = false) {
621
+        if (is_null($languageCode)) {
622
+            $languageCode = \OC::$server->getL10NFactory()->findLanguage($application);
623
+        }
624
+        if (!empty($application)) {
625
+            $path = "$application/l10n/$languageCode";
626
+        } else {
627
+            $path = "l10n/$languageCode";
628
+        }
629
+        self::addExternalResource($application, $prepend, $path, "script");
630
+    }
631
+
632
+    /**
633
+     * add a css file
634
+     *
635
+     * @param string $application application id
636
+     * @param string|null $file filename
637
+     * @param bool $prepend prepend the Style to the beginning of the list
638
+     * @return void
639
+     */
640
+    public static function addStyle($application, $file = null, $prepend = false) {
641
+        $path = OC_Util::generatePath($application, 'css', $file);
642
+        self::addExternalResource($application, $prepend, $path, "style");
643
+    }
644
+
645
+    /**
646
+     * add a css file from the vendor sub folder
647
+     *
648
+     * @param string $application application id
649
+     * @param string|null $file filename
650
+     * @param bool $prepend prepend the Style to the beginning of the list
651
+     * @return void
652
+     */
653
+    public static function addVendorStyle($application, $file = null, $prepend = false) {
654
+        $path = OC_Util::generatePath($application, 'vendor', $file);
655
+        self::addExternalResource($application, $prepend, $path, "style");
656
+    }
657
+
658
+    /**
659
+     * add an external resource css/js file
660
+     *
661
+     * @param string $application application id
662
+     * @param bool $prepend prepend the file to the beginning of the list
663
+     * @param string $path
664
+     * @param string $type (script or style)
665
+     * @return void
666
+     */
667
+    private static function addExternalResource($application, $prepend, $path, $type = "script") {
668
+
669
+        if ($type === "style") {
670
+            if (!in_array($path, self::$styles)) {
671
+                if ($prepend === true) {
672
+                    array_unshift ( self::$styles, $path );
673
+                } else {
674
+                    self::$styles[] = $path;
675
+                }
676
+            }
677
+        } elseif ($type === "script") {
678
+            if (!in_array($path, self::$scripts)) {
679
+                if ($prepend === true) {
680
+                    array_unshift ( self::$scripts, $path );
681
+                } else {
682
+                    self::$scripts [] = $path;
683
+                }
684
+            }
685
+        }
686
+    }
687
+
688
+    /**
689
+     * Add a custom element to the header
690
+     * If $text is null then the element will be written as empty element.
691
+     * So use "" to get a closing tag.
692
+     * @param string $tag tag name of the element
693
+     * @param array $attributes array of attributes for the element
694
+     * @param string $text the text content for the element
695
+     * @param bool $prepend prepend the header to the beginning of the list
696
+     */
697
+    public static function addHeader($tag, $attributes, $text = null, $prepend = false) {
698
+        $header = [
699
+            'tag' => $tag,
700
+            'attributes' => $attributes,
701
+            'text' => $text
702
+        ];
703
+        if ($prepend === true) {
704
+            array_unshift (self::$headers, $header);
705
+
706
+        } else {
707
+            self::$headers[] = $header;
708
+        }
709
+    }
710
+
711
+    /**
712
+     * check if the current server configuration is suitable for ownCloud
713
+     *
714
+     * @param \OC\SystemConfig $config
715
+     * @return array arrays with error messages and hints
716
+     */
717
+    public static function checkServer(\OC\SystemConfig $config) {
718
+        $l = \OC::$server->getL10N('lib');
719
+        $errors = [];
720
+        $CONFIG_DATADIRECTORY = $config->getValue('datadirectory', OC::$SERVERROOT . '/data');
721
+
722
+        if (!self::needUpgrade($config) && $config->getValue('installed', false)) {
723
+            // this check needs to be done every time
724
+            $errors = self::checkDataDirectoryValidity($CONFIG_DATADIRECTORY);
725
+        }
726
+
727
+        // Assume that if checkServer() succeeded before in this session, then all is fine.
728
+        if (\OC::$server->getSession()->exists('checkServer_succeeded') && \OC::$server->getSession()->get('checkServer_succeeded')) {
729
+            return $errors;
730
+        }
731
+
732
+        $webServerRestart = false;
733
+        $setup = new \OC\Setup(
734
+            $config,
735
+            \OC::$server->getIniWrapper(),
736
+            \OC::$server->getL10N('lib'),
737
+            \OC::$server->query(\OCP\Defaults::class),
738
+            \OC::$server->getLogger(),
739
+            \OC::$server->getSecureRandom(),
740
+            \OC::$server->query(\OC\Installer::class)
741
+        );
742
+
743
+        $urlGenerator = \OC::$server->getURLGenerator();
744
+
745
+        $availableDatabases = $setup->getSupportedDatabases();
746
+        if (empty($availableDatabases)) {
747
+            $errors[] = [
748
+                'error' => $l->t('No database drivers (sqlite, mysql, or postgresql) installed.'),
749
+                'hint' => '' //TODO: sane hint
750
+            ];
751
+            $webServerRestart = true;
752
+        }
753
+
754
+        // Check if config folder is writable.
755
+        if(!OC_Helper::isReadOnlyConfigEnabled()) {
756
+            if (!is_writable(OC::$configDir) or !is_readable(OC::$configDir)) {
757
+                $errors[] = [
758
+                    'error' => $l->t('Cannot write into "config" directory'),
759
+                    'hint' => $l->t('This can usually be fixed by giving the webserver write access to the config directory. See %s',
760
+                        [ $urlGenerator->linkToDocs('admin-dir_permissions') ]) . '. '
761
+                        . $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it. See %s',
762
+                        [ $urlGenerator->linkToDocs('admin-config') ] )
763
+                ];
764
+            }
765
+        }
766
+
767
+        // Check if there is a writable install folder.
768
+        if ($config->getValue('appstoreenabled', true)) {
769
+            if (OC_App::getInstallPath() === null
770
+                || !is_writable(OC_App::getInstallPath())
771
+                || !is_readable(OC_App::getInstallPath())
772
+            ) {
773
+                $errors[] = [
774
+                    'error' => $l->t('Cannot write into "apps" directory'),
775
+                    'hint' => $l->t('This can usually be fixed by giving the webserver write access to the apps directory'
776
+                        . ' or disabling the appstore in the config file. See %s',
777
+                        [$urlGenerator->linkToDocs('admin-dir_permissions')])
778
+                ];
779
+            }
780
+        }
781
+        // Create root dir.
782
+        if ($config->getValue('installed', false)) {
783
+            if (!is_dir($CONFIG_DATADIRECTORY)) {
784
+                $success = @mkdir($CONFIG_DATADIRECTORY);
785
+                if ($success) {
786
+                    $errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY));
787
+                } else {
788
+                    $errors[] = [
789
+                        'error' => $l->t('Cannot create "data" directory'),
790
+                        'hint' => $l->t('This can usually be fixed by giving the webserver write access to the root directory. See %s',
791
+                            [$urlGenerator->linkToDocs('admin-dir_permissions')])
792
+                    ];
793
+                }
794
+            } else if (!is_writable($CONFIG_DATADIRECTORY) or !is_readable($CONFIG_DATADIRECTORY)) {
795
+                // is_writable doesn't work for NFS mounts, so try to write a file and check if it exists.
796
+                $testFile = sprintf('%s/%s.tmp', $CONFIG_DATADIRECTORY, uniqid('data_dir_writability_test_'));
797
+                $handle = fopen($testFile, 'w');
798
+                if (!$handle || fwrite($handle, 'Test write operation') === false) {
799
+                    $permissionsHint = $l->t('Permissions can usually be fixed by giving the webserver write access to the root directory. See %s.',
800
+                        [$urlGenerator->linkToDocs('admin-dir_permissions')]);
801
+                    $errors[] = [
802
+                        'error' => 'Your data directory is not writable',
803
+                        'hint' => $permissionsHint
804
+                    ];
805
+                } else {
806
+                    fclose($handle);
807
+                    unlink($testFile);
808
+                }
809
+            } else {
810
+                $errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY));
811
+            }
812
+        }
813
+
814
+        if (!OC_Util::isSetLocaleWorking()) {
815
+            $errors[] = [
816
+                'error' => $l->t('Setting locale to %s failed',
817
+                    ['en_US.UTF-8/fr_FR.UTF-8/es_ES.UTF-8/de_DE.UTF-8/ru_RU.UTF-8/'
818
+                        . 'pt_BR.UTF-8/it_IT.UTF-8/ja_JP.UTF-8/zh_CN.UTF-8']),
819
+                'hint' => $l->t('Please install one of these locales on your system and restart your webserver.')
820
+            ];
821
+        }
822
+
823
+        // Contains the dependencies that should be checked against
824
+        // classes = class_exists
825
+        // functions = function_exists
826
+        // defined = defined
827
+        // ini = ini_get
828
+        // If the dependency is not found the missing module name is shown to the EndUser
829
+        // When adding new checks always verify that they pass on Travis as well
830
+        // for ini settings, see https://github.com/owncloud/administration/blob/master/travis-ci/custom.ini
831
+        $dependencies = [
832
+            'classes' => [
833
+                'ZipArchive' => 'zip',
834
+                'DOMDocument' => 'dom',
835
+                'XMLWriter' => 'XMLWriter',
836
+                'XMLReader' => 'XMLReader',
837
+            ],
838
+            'functions' => [
839
+                'xml_parser_create' => 'libxml',
840
+                'mb_strcut' => 'mbstring',
841
+                'ctype_digit' => 'ctype',
842
+                'json_encode' => 'JSON',
843
+                'gd_info' => 'GD',
844
+                'gzencode' => 'zlib',
845
+                'iconv' => 'iconv',
846
+                'simplexml_load_string' => 'SimpleXML',
847
+                'hash' => 'HASH Message Digest Framework',
848
+                'curl_init' => 'cURL',
849
+                'openssl_verify' => 'OpenSSL',
850
+            ],
851
+            'defined' => [
852
+                'PDO::ATTR_DRIVER_NAME' => 'PDO'
853
+            ],
854
+            'ini' => [
855
+                'default_charset' => 'UTF-8',
856
+            ],
857
+        ];
858
+        $missingDependencies = [];
859
+        $invalidIniSettings = [];
860
+        $moduleHint = $l->t('Please ask your server administrator to install the module.');
861
+
862
+        $iniWrapper = \OC::$server->getIniWrapper();
863
+        foreach ($dependencies['classes'] as $class => $module) {
864
+            if (!class_exists($class)) {
865
+                $missingDependencies[] = $module;
866
+            }
867
+        }
868
+        foreach ($dependencies['functions'] as $function => $module) {
869
+            if (!function_exists($function)) {
870
+                $missingDependencies[] = $module;
871
+            }
872
+        }
873
+        foreach ($dependencies['defined'] as $defined => $module) {
874
+            if (!defined($defined)) {
875
+                $missingDependencies[] = $module;
876
+            }
877
+        }
878
+        foreach ($dependencies['ini'] as $setting => $expected) {
879
+            if (is_bool($expected)) {
880
+                if ($iniWrapper->getBool($setting) !== $expected) {
881
+                    $invalidIniSettings[] = [$setting, $expected];
882
+                }
883
+            }
884
+            if (is_int($expected)) {
885
+                if ($iniWrapper->getNumeric($setting) !== $expected) {
886
+                    $invalidIniSettings[] = [$setting, $expected];
887
+                }
888
+            }
889
+            if (is_string($expected)) {
890
+                if (strtolower($iniWrapper->getString($setting)) !== strtolower($expected)) {
891
+                    $invalidIniSettings[] = [$setting, $expected];
892
+                }
893
+            }
894
+        }
895
+
896
+        foreach($missingDependencies as $missingDependency) {
897
+            $errors[] = [
898
+                'error' => $l->t('PHP module %s not installed.', [$missingDependency]),
899
+                'hint' => $moduleHint
900
+            ];
901
+            $webServerRestart = true;
902
+        }
903
+        foreach($invalidIniSettings as $setting) {
904
+            if(is_bool($setting[1])) {
905
+                $setting[1] = $setting[1] ? 'on' : 'off';
906
+            }
907
+            $errors[] = [
908
+                'error' => $l->t('PHP setting "%s" is not set to "%s".', [$setting[0], var_export($setting[1], true)]),
909
+                'hint' =>  $l->t('Adjusting this setting in php.ini will make Nextcloud run again')
910
+            ];
911
+            $webServerRestart = true;
912
+        }
913
+
914
+        /**
915
+         * The mbstring.func_overload check can only be performed if the mbstring
916
+         * module is installed as it will return null if the checking setting is
917
+         * not available and thus a check on the boolean value fails.
918
+         *
919
+         * TODO: Should probably be implemented in the above generic dependency
920
+         *       check somehow in the long-term.
921
+         */
922
+        if($iniWrapper->getBool('mbstring.func_overload') !== null &&
923
+            $iniWrapper->getBool('mbstring.func_overload') === true) {
924
+            $errors[] = [
925
+                'error' => $l->t('mbstring.func_overload is set to "%s" instead of the expected value "0"', [$iniWrapper->getString('mbstring.func_overload')]),
926
+                'hint' => $l->t('To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini')
927
+            ];
928
+        }
929
+
930
+        if(function_exists('xml_parser_create') &&
931
+            LIBXML_LOADED_VERSION < 20700 ) {
932
+            $version = LIBXML_LOADED_VERSION;
933
+            $major = floor($version/10000);
934
+            $version -= ($major * 10000);
935
+            $minor = floor($version/100);
936
+            $version -= ($minor * 100);
937
+            $patch = $version;
938
+            $errors[] = [
939
+                'error' => $l->t('libxml2 2.7.0 is at least required. Currently %s is installed.', [$major . '.' . $minor . '.' . $patch]),
940
+                'hint' => $l->t('To fix this issue update your libxml2 version and restart your web server.')
941
+            ];
942
+        }
943
+
944
+        if (!self::isAnnotationsWorking()) {
945
+            $errors[] = [
946
+                'error' => $l->t('PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible.'),
947
+                'hint' => $l->t('This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator.')
948
+            ];
949
+        }
950
+
951
+        if (!\OC::$CLI && $webServerRestart) {
952
+            $errors[] = [
953
+                'error' => $l->t('PHP modules have been installed, but they are still listed as missing?'),
954
+                'hint' => $l->t('Please ask your server administrator to restart the web server.')
955
+            ];
956
+        }
957
+
958
+        $errors = array_merge($errors, self::checkDatabaseVersion());
959
+
960
+        // Cache the result of this function
961
+        \OC::$server->getSession()->set('checkServer_succeeded', count($errors) == 0);
962
+
963
+        return $errors;
964
+    }
965
+
966
+    /**
967
+     * Check the database version
968
+     *
969
+     * @return array errors array
970
+     */
971
+    public static function checkDatabaseVersion() {
972
+        $l = \OC::$server->getL10N('lib');
973
+        $errors = [];
974
+        $dbType = \OC::$server->getSystemConfig()->getValue('dbtype', 'sqlite');
975
+        if ($dbType === 'pgsql') {
976
+            // check PostgreSQL version
977
+            try {
978
+                $result = \OC_DB::executeAudited('SHOW SERVER_VERSION');
979
+                $data = $result->fetchRow();
980
+                if (isset($data['server_version'])) {
981
+                    $version = $data['server_version'];
982
+                    if (version_compare($version, '9.0.0', '<')) {
983
+                        $errors[] = [
984
+                            'error' => $l->t('PostgreSQL >= 9 required'),
985
+                            'hint' => $l->t('Please upgrade your database version')
986
+                        ];
987
+                    }
988
+                }
989
+            } catch (\Doctrine\DBAL\DBALException $e) {
990
+                $logger = \OC::$server->getLogger();
991
+                $logger->warning('Error occurred while checking PostgreSQL version, assuming >= 9');
992
+                $logger->logException($e);
993
+            }
994
+        }
995
+        return $errors;
996
+    }
997
+
998
+    /**
999
+     * Check for correct file permissions of data directory
1000
+     *
1001
+     * @param string $dataDirectory
1002
+     * @return array arrays with error messages and hints
1003
+     */
1004
+    public static function checkDataDirectoryPermissions($dataDirectory) {
1005
+        if(\OC::$server->getConfig()->getSystemValue('check_data_directory_permissions', true) === false) {
1006
+            return  [];
1007
+        }
1008
+        $l = \OC::$server->getL10N('lib');
1009
+        $errors = [];
1010
+        $permissionsModHint = $l->t('Please change the permissions to 0770 so that the directory'
1011
+            . ' cannot be listed by other users.');
1012
+        $perms = substr(decoct(@fileperms($dataDirectory)), -3);
1013
+        if (substr($perms, -1) !== '0') {
1014
+            chmod($dataDirectory, 0770);
1015
+            clearstatcache();
1016
+            $perms = substr(decoct(@fileperms($dataDirectory)), -3);
1017
+            if ($perms[2] !== '0') {
1018
+                $errors[] = [
1019
+                    'error' => $l->t('Your data directory is readable by other users'),
1020
+                    'hint' => $permissionsModHint
1021
+                ];
1022
+            }
1023
+        }
1024
+        return $errors;
1025
+    }
1026
+
1027
+    /**
1028
+     * Check that the data directory exists and is valid by
1029
+     * checking the existence of the ".ocdata" file.
1030
+     *
1031
+     * @param string $dataDirectory data directory path
1032
+     * @return array errors found
1033
+     */
1034
+    public static function checkDataDirectoryValidity($dataDirectory) {
1035
+        $l = \OC::$server->getL10N('lib');
1036
+        $errors = [];
1037
+        if ($dataDirectory[0] !== '/') {
1038
+            $errors[] = [
1039
+                'error' => $l->t('Your data directory must be an absolute path'),
1040
+                'hint' => $l->t('Check the value of "datadirectory" in your configuration')
1041
+            ];
1042
+        }
1043
+        if (!file_exists($dataDirectory . '/.ocdata')) {
1044
+            $errors[] = [
1045
+                'error' => $l->t('Your data directory is invalid'),
1046
+                'hint' => $l->t('Ensure there is a file called ".ocdata"' .
1047
+                    ' in the root of the data directory.')
1048
+            ];
1049
+        }
1050
+        return $errors;
1051
+    }
1052
+
1053
+    /**
1054
+     * Check if the user is logged in, redirects to home if not. With
1055
+     * redirect URL parameter to the request URI.
1056
+     *
1057
+     * @return void
1058
+     */
1059
+    public static function checkLoggedIn() {
1060
+        // Check if we are a user
1061
+        if (!\OC::$server->getUserSession()->isLoggedIn()) {
1062
+            header('Location: ' . \OC::$server->getURLGenerator()->linkToRoute(
1063
+                        'core.login.showLoginForm',
1064
+                        [
1065
+                            'redirect_url' => \OC::$server->getRequest()->getRequestUri(),
1066
+                        ]
1067
+                    )
1068
+            );
1069
+            exit();
1070
+        }
1071
+        // Redirect to 2FA challenge selection if 2FA challenge was not solved yet
1072
+        if (\OC::$server->getTwoFactorAuthManager()->needsSecondFactor(\OC::$server->getUserSession()->getUser())) {
1073
+            header('Location: ' . \OC::$server->getURLGenerator()->linkToRoute('core.TwoFactorChallenge.selectChallenge'));
1074
+            exit();
1075
+        }
1076
+    }
1077
+
1078
+    /**
1079
+     * Check if the user is a admin, redirects to home if not
1080
+     *
1081
+     * @return void
1082
+     */
1083
+    public static function checkAdminUser() {
1084
+        OC_Util::checkLoggedIn();
1085
+        if (!OC_User::isAdminUser(OC_User::getUser())) {
1086
+            header('Location: ' . \OCP\Util::linkToAbsolute('', 'index.php'));
1087
+            exit();
1088
+        }
1089
+    }
1090
+
1091
+    /**
1092
+     * Returns the URL of the default page
1093
+     * based on the system configuration and
1094
+     * the apps visible for the current user
1095
+     *
1096
+     * @return string URL
1097
+     * @suppress PhanDeprecatedFunction
1098
+     */
1099
+    public static function getDefaultPageUrl() {
1100
+        $urlGenerator = \OC::$server->getURLGenerator();
1101
+        // Deny the redirect if the URL contains a @
1102
+        // This prevents unvalidated redirects like ?redirect_url=:[email protected]
1103
+        if (isset($_REQUEST['redirect_url']) && strpos($_REQUEST['redirect_url'], '@') === false) {
1104
+            $location = $urlGenerator->getAbsoluteURL(urldecode($_REQUEST['redirect_url']));
1105
+        } else {
1106
+            $defaultPage = \OC::$server->getConfig()->getAppValue('core', 'defaultpage');
1107
+            if ($defaultPage) {
1108
+                $location = $urlGenerator->getAbsoluteURL($defaultPage);
1109
+            } else {
1110
+                $appId = 'files';
1111
+                $config = \OC::$server->getConfig();
1112
+                $defaultApps = explode(',', $config->getSystemValue('defaultapp', 'files'));
1113
+                // find the first app that is enabled for the current user
1114
+                foreach ($defaultApps as $defaultApp) {
1115
+                    $defaultApp = OC_App::cleanAppId(strip_tags($defaultApp));
1116
+                    if (static::getAppManager()->isEnabledForUser($defaultApp)) {
1117
+                        $appId = $defaultApp;
1118
+                        break;
1119
+                    }
1120
+                }
1121
+
1122
+                if($config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true') {
1123
+                    $location = $urlGenerator->getAbsoluteURL('/apps/' . $appId . '/');
1124
+                } else {
1125
+                    $location = $urlGenerator->getAbsoluteURL('/index.php/apps/' . $appId . '/');
1126
+                }
1127
+            }
1128
+        }
1129
+        return $location;
1130
+    }
1131
+
1132
+    /**
1133
+     * Redirect to the user default page
1134
+     *
1135
+     * @return void
1136
+     */
1137
+    public static function redirectToDefaultPage() {
1138
+        $location = self::getDefaultPageUrl();
1139
+        header('Location: ' . $location);
1140
+        exit();
1141
+    }
1142
+
1143
+    /**
1144
+     * get an id unique for this instance
1145
+     *
1146
+     * @return string
1147
+     */
1148
+    public static function getInstanceId() {
1149
+        $id = \OC::$server->getSystemConfig()->getValue('instanceid', null);
1150
+        if (is_null($id)) {
1151
+            // We need to guarantee at least one letter in instanceid so it can be used as the session_name
1152
+            $id = 'oc' . \OC::$server->getSecureRandom()->generate(10, \OCP\Security\ISecureRandom::CHAR_LOWER.\OCP\Security\ISecureRandom::CHAR_DIGITS);
1153
+            \OC::$server->getSystemConfig()->setValue('instanceid', $id);
1154
+        }
1155
+        return $id;
1156
+    }
1157
+
1158
+    /**
1159
+     * Public function to sanitize HTML
1160
+     *
1161
+     * This function is used to sanitize HTML and should be applied on any
1162
+     * string or array of strings before displaying it on a web page.
1163
+     *
1164
+     * @param string|array $value
1165
+     * @return string|array an array of sanitized strings or a single sanitized string, depends on the input parameter.
1166
+     */
1167
+    public static function sanitizeHTML($value) {
1168
+        if (is_array($value)) {
1169
+            $value = array_map(function($value) {
1170
+                return self::sanitizeHTML($value);
1171
+            }, $value);
1172
+        } else {
1173
+            // Specify encoding for PHP<5.4
1174
+            $value = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
1175
+        }
1176
+        return $value;
1177
+    }
1178
+
1179
+    /**
1180
+     * Public function to encode url parameters
1181
+     *
1182
+     * This function is used to encode path to file before output.
1183
+     * Encoding is done according to RFC 3986 with one exception:
1184
+     * Character '/' is preserved as is.
1185
+     *
1186
+     * @param string $component part of URI to encode
1187
+     * @return string
1188
+     */
1189
+    public static function encodePath($component) {
1190
+        $encoded = rawurlencode($component);
1191
+        $encoded = str_replace('%2F', '/', $encoded);
1192
+        return $encoded;
1193
+    }
1194
+
1195
+
1196
+    public function createHtaccessTestFile(\OCP\IConfig $config) {
1197
+        // php dev server does not support htaccess
1198
+        if (php_sapi_name() === 'cli-server') {
1199
+            return false;
1200
+        }
1201
+
1202
+        // testdata
1203
+        $fileName = '/htaccesstest.txt';
1204
+        $testContent = 'This is used for testing whether htaccess is properly enabled to disallow access from the outside. This file can be safely removed.';
1205
+
1206
+        // creating a test file
1207
+        $testFile = $config->getSystemValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $fileName;
1208
+
1209
+        if (file_exists($testFile)) {// already running this test, possible recursive call
1210
+            return false;
1211
+        }
1212
+
1213
+        $fp = @fopen($testFile, 'w');
1214
+        if (!$fp) {
1215
+            throw new OC\HintException('Can\'t create test file to check for working .htaccess file.',
1216
+                'Make sure it is possible for the webserver to write to ' . $testFile);
1217
+        }
1218
+        fwrite($fp, $testContent);
1219
+        fclose($fp);
1220
+
1221
+        return $testContent;
1222
+    }
1223
+
1224
+    /**
1225
+     * Check if the .htaccess file is working
1226
+     * @param \OCP\IConfig $config
1227
+     * @return bool
1228
+     * @throws Exception
1229
+     * @throws \OC\HintException If the test file can't get written.
1230
+     */
1231
+    public function isHtaccessWorking(\OCP\IConfig $config) {
1232
+
1233
+        if (\OC::$CLI || !$config->getSystemValue('check_for_working_htaccess', true)) {
1234
+            return true;
1235
+        }
1236
+
1237
+        $testContent = $this->createHtaccessTestFile($config);
1238
+        if ($testContent === false) {
1239
+            return false;
1240
+        }
1241
+
1242
+        $fileName = '/htaccesstest.txt';
1243
+        $testFile = $config->getSystemValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $fileName;
1244
+
1245
+        // accessing the file via http
1246
+        $url = \OC::$server->getURLGenerator()->getAbsoluteURL(OC::$WEBROOT . '/data' . $fileName);
1247
+        try {
1248
+            $content = \OC::$server->getHTTPClientService()->newClient()->get($url)->getBody();
1249
+        } catch (\Exception $e) {
1250
+            $content = false;
1251
+        }
1252
+
1253
+        if (strpos($url, 'https:') === 0) {
1254
+            $url = 'http:' . substr($url, 6);
1255
+        } else {
1256
+            $url = 'https:' . substr($url, 5);
1257
+        }
1258
+
1259
+        try {
1260
+            $fallbackContent = \OC::$server->getHTTPClientService()->newClient()->get($url)->getBody();
1261
+        } catch (\Exception $e) {
1262
+            $fallbackContent = false;
1263
+        }
1264
+
1265
+        // cleanup
1266
+        @unlink($testFile);
1267
+
1268
+        /*
1269 1269
 		 * If the content is not equal to test content our .htaccess
1270 1270
 		 * is working as required
1271 1271
 		 */
1272
-		return $content !== $testContent && $fallbackContent !== $testContent;
1273
-	}
1274
-
1275
-	/**
1276
-	 * Check if the setlocal call does not work. This can happen if the right
1277
-	 * local packages are not available on the server.
1278
-	 *
1279
-	 * @return bool
1280
-	 */
1281
-	public static function isSetLocaleWorking() {
1282
-		\Patchwork\Utf8\Bootup::initLocale();
1283
-		if ('' === basename('§')) {
1284
-			return false;
1285
-		}
1286
-		return true;
1287
-	}
1288
-
1289
-	/**
1290
-	 * Check if it's possible to get the inline annotations
1291
-	 *
1292
-	 * @return bool
1293
-	 */
1294
-	public static function isAnnotationsWorking() {
1295
-		$reflection = new \ReflectionMethod(__METHOD__);
1296
-		$docs = $reflection->getDocComment();
1297
-
1298
-		return (is_string($docs) && strlen($docs) > 50);
1299
-	}
1300
-
1301
-	/**
1302
-	 * Check if the PHP module fileinfo is loaded.
1303
-	 *
1304
-	 * @return bool
1305
-	 */
1306
-	public static function fileInfoLoaded() {
1307
-		return function_exists('finfo_open');
1308
-	}
1309
-
1310
-	/**
1311
-	 * clear all levels of output buffering
1312
-	 *
1313
-	 * @return void
1314
-	 */
1315
-	public static function obEnd() {
1316
-		while (ob_get_level()) {
1317
-			ob_end_clean();
1318
-		}
1319
-	}
1320
-
1321
-	/**
1322
-	 * Checks whether the server is running on Mac OS X
1323
-	 *
1324
-	 * @return bool true if running on Mac OS X, false otherwise
1325
-	 */
1326
-	public static function runningOnMac() {
1327
-		return (strtoupper(substr(PHP_OS, 0, 6)) === 'DARWIN');
1328
-	}
1329
-
1330
-	/**
1331
-	 * Handles the case that there may not be a theme, then check if a "default"
1332
-	 * theme exists and take that one
1333
-	 *
1334
-	 * @return string the theme
1335
-	 */
1336
-	public static function getTheme() {
1337
-		$theme = \OC::$server->getSystemConfig()->getValue("theme", '');
1338
-
1339
-		if ($theme === '') {
1340
-			if (is_dir(OC::$SERVERROOT . '/themes/default')) {
1341
-				$theme = 'default';
1342
-			}
1343
-		}
1344
-
1345
-		return $theme;
1346
-	}
1347
-
1348
-	/**
1349
-	 * Normalize a unicode string
1350
-	 *
1351
-	 * @param string $value a not normalized string
1352
-	 * @return bool|string
1353
-	 */
1354
-	public static function normalizeUnicode($value) {
1355
-		if(Normalizer::isNormalized($value)) {
1356
-			return $value;
1357
-		}
1358
-
1359
-		$normalizedValue = Normalizer::normalize($value);
1360
-		if ($normalizedValue === null || $normalizedValue === false) {
1361
-			\OC::$server->getLogger()->warning('normalizing failed for "' . $value . '"', ['app' => 'core']);
1362
-			return $value;
1363
-		}
1364
-
1365
-		return $normalizedValue;
1366
-	}
1367
-
1368
-	/**
1369
-	 * A human readable string is generated based on version and build number
1370
-	 *
1371
-	 * @return string
1372
-	 */
1373
-	public static function getHumanVersion() {
1374
-		$version = OC_Util::getVersionString();
1375
-		$build = OC_Util::getBuild();
1376
-		if (!empty($build) and OC_Util::getChannel() === 'daily') {
1377
-			$version .= ' Build:' . $build;
1378
-		}
1379
-		return $version;
1380
-	}
1381
-
1382
-	/**
1383
-	 * Returns whether the given file name is valid
1384
-	 *
1385
-	 * @param string $file file name to check
1386
-	 * @return bool true if the file name is valid, false otherwise
1387
-	 * @deprecated use \OC\Files\View::verifyPath()
1388
-	 */
1389
-	public static function isValidFileName($file) {
1390
-		$trimmed = trim($file);
1391
-		if ($trimmed === '') {
1392
-			return false;
1393
-		}
1394
-		if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) {
1395
-			return false;
1396
-		}
1397
-
1398
-		// detect part files
1399
-		if (preg_match('/' . \OCP\Files\FileInfo::BLACKLIST_FILES_REGEX . '/', $trimmed) !== 0) {
1400
-			return false;
1401
-		}
1402
-
1403
-		foreach (str_split($trimmed) as $char) {
1404
-			if (strpos(\OCP\Constants::FILENAME_INVALID_CHARS, $char) !== false) {
1405
-				return false;
1406
-			}
1407
-		}
1408
-		return true;
1409
-	}
1410
-
1411
-	/**
1412
-	 * Check whether the instance needs to perform an upgrade,
1413
-	 * either when the core version is higher or any app requires
1414
-	 * an upgrade.
1415
-	 *
1416
-	 * @param \OC\SystemConfig $config
1417
-	 * @return bool whether the core or any app needs an upgrade
1418
-	 * @throws \OC\HintException When the upgrade from the given version is not allowed
1419
-	 */
1420
-	public static function needUpgrade(\OC\SystemConfig $config) {
1421
-		if ($config->getValue('installed', false)) {
1422
-			$installedVersion = $config->getValue('version', '0.0.0');
1423
-			$currentVersion = implode('.', \OCP\Util::getVersion());
1424
-			$versionDiff = version_compare($currentVersion, $installedVersion);
1425
-			if ($versionDiff > 0) {
1426
-				return true;
1427
-			} else if ($config->getValue('debug', false) && $versionDiff < 0) {
1428
-				// downgrade with debug
1429
-				$installedMajor = explode('.', $installedVersion);
1430
-				$installedMajor = $installedMajor[0] . '.' . $installedMajor[1];
1431
-				$currentMajor = explode('.', $currentVersion);
1432
-				$currentMajor = $currentMajor[0] . '.' . $currentMajor[1];
1433
-				if ($installedMajor === $currentMajor) {
1434
-					// Same major, allow downgrade for developers
1435
-					return true;
1436
-				} else {
1437
-					// downgrade attempt, throw exception
1438
-					throw new \OC\HintException('Downgrading is not supported and is likely to cause unpredictable issues (from ' . $installedVersion . ' to ' . $currentVersion . ')');
1439
-				}
1440
-			} else if ($versionDiff < 0) {
1441
-				// downgrade attempt, throw exception
1442
-				throw new \OC\HintException('Downgrading is not supported and is likely to cause unpredictable issues (from ' . $installedVersion . ' to ' . $currentVersion . ')');
1443
-			}
1444
-
1445
-			// also check for upgrades for apps (independently from the user)
1446
-			$apps = \OC_App::getEnabledApps(false, true);
1447
-			$shouldUpgrade = false;
1448
-			foreach ($apps as $app) {
1449
-				if (\OC_App::shouldUpgrade($app)) {
1450
-					$shouldUpgrade = true;
1451
-					break;
1452
-				}
1453
-			}
1454
-			return $shouldUpgrade;
1455
-		} else {
1456
-			return false;
1457
-		}
1458
-	}
1459
-
1460
-	/**
1461
-	 * is this Internet explorer ?
1462
-	 *
1463
-	 * @return boolean
1464
-	 */
1465
-	public static function isIe() {
1466
-		if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1467
-			return false;
1468
-		}
1469
-
1470
-		return preg_match(Request::USER_AGENT_IE, $_SERVER['HTTP_USER_AGENT']) === 1;
1471
-	}
1272
+        return $content !== $testContent && $fallbackContent !== $testContent;
1273
+    }
1274
+
1275
+    /**
1276
+     * Check if the setlocal call does not work. This can happen if the right
1277
+     * local packages are not available on the server.
1278
+     *
1279
+     * @return bool
1280
+     */
1281
+    public static function isSetLocaleWorking() {
1282
+        \Patchwork\Utf8\Bootup::initLocale();
1283
+        if ('' === basename('§')) {
1284
+            return false;
1285
+        }
1286
+        return true;
1287
+    }
1288
+
1289
+    /**
1290
+     * Check if it's possible to get the inline annotations
1291
+     *
1292
+     * @return bool
1293
+     */
1294
+    public static function isAnnotationsWorking() {
1295
+        $reflection = new \ReflectionMethod(__METHOD__);
1296
+        $docs = $reflection->getDocComment();
1297
+
1298
+        return (is_string($docs) && strlen($docs) > 50);
1299
+    }
1300
+
1301
+    /**
1302
+     * Check if the PHP module fileinfo is loaded.
1303
+     *
1304
+     * @return bool
1305
+     */
1306
+    public static function fileInfoLoaded() {
1307
+        return function_exists('finfo_open');
1308
+    }
1309
+
1310
+    /**
1311
+     * clear all levels of output buffering
1312
+     *
1313
+     * @return void
1314
+     */
1315
+    public static function obEnd() {
1316
+        while (ob_get_level()) {
1317
+            ob_end_clean();
1318
+        }
1319
+    }
1320
+
1321
+    /**
1322
+     * Checks whether the server is running on Mac OS X
1323
+     *
1324
+     * @return bool true if running on Mac OS X, false otherwise
1325
+     */
1326
+    public static function runningOnMac() {
1327
+        return (strtoupper(substr(PHP_OS, 0, 6)) === 'DARWIN');
1328
+    }
1329
+
1330
+    /**
1331
+     * Handles the case that there may not be a theme, then check if a "default"
1332
+     * theme exists and take that one
1333
+     *
1334
+     * @return string the theme
1335
+     */
1336
+    public static function getTheme() {
1337
+        $theme = \OC::$server->getSystemConfig()->getValue("theme", '');
1338
+
1339
+        if ($theme === '') {
1340
+            if (is_dir(OC::$SERVERROOT . '/themes/default')) {
1341
+                $theme = 'default';
1342
+            }
1343
+        }
1344
+
1345
+        return $theme;
1346
+    }
1347
+
1348
+    /**
1349
+     * Normalize a unicode string
1350
+     *
1351
+     * @param string $value a not normalized string
1352
+     * @return bool|string
1353
+     */
1354
+    public static function normalizeUnicode($value) {
1355
+        if(Normalizer::isNormalized($value)) {
1356
+            return $value;
1357
+        }
1358
+
1359
+        $normalizedValue = Normalizer::normalize($value);
1360
+        if ($normalizedValue === null || $normalizedValue === false) {
1361
+            \OC::$server->getLogger()->warning('normalizing failed for "' . $value . '"', ['app' => 'core']);
1362
+            return $value;
1363
+        }
1364
+
1365
+        return $normalizedValue;
1366
+    }
1367
+
1368
+    /**
1369
+     * A human readable string is generated based on version and build number
1370
+     *
1371
+     * @return string
1372
+     */
1373
+    public static function getHumanVersion() {
1374
+        $version = OC_Util::getVersionString();
1375
+        $build = OC_Util::getBuild();
1376
+        if (!empty($build) and OC_Util::getChannel() === 'daily') {
1377
+            $version .= ' Build:' . $build;
1378
+        }
1379
+        return $version;
1380
+    }
1381
+
1382
+    /**
1383
+     * Returns whether the given file name is valid
1384
+     *
1385
+     * @param string $file file name to check
1386
+     * @return bool true if the file name is valid, false otherwise
1387
+     * @deprecated use \OC\Files\View::verifyPath()
1388
+     */
1389
+    public static function isValidFileName($file) {
1390
+        $trimmed = trim($file);
1391
+        if ($trimmed === '') {
1392
+            return false;
1393
+        }
1394
+        if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) {
1395
+            return false;
1396
+        }
1397
+
1398
+        // detect part files
1399
+        if (preg_match('/' . \OCP\Files\FileInfo::BLACKLIST_FILES_REGEX . '/', $trimmed) !== 0) {
1400
+            return false;
1401
+        }
1402
+
1403
+        foreach (str_split($trimmed) as $char) {
1404
+            if (strpos(\OCP\Constants::FILENAME_INVALID_CHARS, $char) !== false) {
1405
+                return false;
1406
+            }
1407
+        }
1408
+        return true;
1409
+    }
1410
+
1411
+    /**
1412
+     * Check whether the instance needs to perform an upgrade,
1413
+     * either when the core version is higher or any app requires
1414
+     * an upgrade.
1415
+     *
1416
+     * @param \OC\SystemConfig $config
1417
+     * @return bool whether the core or any app needs an upgrade
1418
+     * @throws \OC\HintException When the upgrade from the given version is not allowed
1419
+     */
1420
+    public static function needUpgrade(\OC\SystemConfig $config) {
1421
+        if ($config->getValue('installed', false)) {
1422
+            $installedVersion = $config->getValue('version', '0.0.0');
1423
+            $currentVersion = implode('.', \OCP\Util::getVersion());
1424
+            $versionDiff = version_compare($currentVersion, $installedVersion);
1425
+            if ($versionDiff > 0) {
1426
+                return true;
1427
+            } else if ($config->getValue('debug', false) && $versionDiff < 0) {
1428
+                // downgrade with debug
1429
+                $installedMajor = explode('.', $installedVersion);
1430
+                $installedMajor = $installedMajor[0] . '.' . $installedMajor[1];
1431
+                $currentMajor = explode('.', $currentVersion);
1432
+                $currentMajor = $currentMajor[0] . '.' . $currentMajor[1];
1433
+                if ($installedMajor === $currentMajor) {
1434
+                    // Same major, allow downgrade for developers
1435
+                    return true;
1436
+                } else {
1437
+                    // downgrade attempt, throw exception
1438
+                    throw new \OC\HintException('Downgrading is not supported and is likely to cause unpredictable issues (from ' . $installedVersion . ' to ' . $currentVersion . ')');
1439
+                }
1440
+            } else if ($versionDiff < 0) {
1441
+                // downgrade attempt, throw exception
1442
+                throw new \OC\HintException('Downgrading is not supported and is likely to cause unpredictable issues (from ' . $installedVersion . ' to ' . $currentVersion . ')');
1443
+            }
1444
+
1445
+            // also check for upgrades for apps (independently from the user)
1446
+            $apps = \OC_App::getEnabledApps(false, true);
1447
+            $shouldUpgrade = false;
1448
+            foreach ($apps as $app) {
1449
+                if (\OC_App::shouldUpgrade($app)) {
1450
+                    $shouldUpgrade = true;
1451
+                    break;
1452
+                }
1453
+            }
1454
+            return $shouldUpgrade;
1455
+        } else {
1456
+            return false;
1457
+        }
1458
+    }
1459
+
1460
+    /**
1461
+     * is this Internet explorer ?
1462
+     *
1463
+     * @return boolean
1464
+     */
1465
+    public static function isIe() {
1466
+        if (!isset($_SERVER['HTTP_USER_AGENT'])) {
1467
+            return false;
1468
+        }
1469
+
1470
+        return preg_match(Request::USER_AGENT_IE, $_SERVER['HTTP_USER_AGENT']) === 1;
1471
+    }
1472 1472
 
1473 1473
 }
Please login to merge, or discard this patch.
lib/private/legacy/user.php 1 patch
Indentation   +350 added lines, -350 removed lines patch added patch discarded remove patch
@@ -59,354 +59,354 @@
 block discarded – undo
59 59
  */
60 60
 class OC_User {
61 61
 
62
-	private static $_usedBackends = [];
63
-
64
-	private static $_setupedBackends = [];
65
-
66
-	// bool, stores if a user want to access a resource anonymously, e.g if they open a public link
67
-	private static $incognitoMode = false;
68
-
69
-	/**
70
-	 * Adds the backend to the list of used backends
71
-	 *
72
-	 * @param string|\OCP\UserInterface $backend default: database The backend to use for user management
73
-	 * @return bool
74
-	 *
75
-	 * Set the User Authentication Module
76
-	 * @suppress PhanDeprecatedFunction
77
-	 */
78
-	public static function useBackend($backend = 'database') {
79
-		if ($backend instanceof \OCP\UserInterface) {
80
-			self::$_usedBackends[get_class($backend)] = $backend;
81
-			\OC::$server->getUserManager()->registerBackend($backend);
82
-		} else {
83
-			// You'll never know what happens
84
-			if (null === $backend OR !is_string($backend)) {
85
-				$backend = 'database';
86
-			}
87
-
88
-			// Load backend
89
-			switch ($backend) {
90
-				case 'database':
91
-				case 'mysql':
92
-				case 'sqlite':
93
-					\OCP\Util::writeLog('core', 'Adding user backend ' . $backend . '.', ILogger::DEBUG);
94
-					self::$_usedBackends[$backend] = new \OC\User\Database();
95
-					\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
96
-					break;
97
-				case 'dummy':
98
-					self::$_usedBackends[$backend] = new \Test\Util\User\Dummy();
99
-					\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
100
-					break;
101
-				default:
102
-					\OCP\Util::writeLog('core', 'Adding default user backend ' . $backend . '.', ILogger::DEBUG);
103
-					$className = 'OC_USER_' . strtoupper($backend);
104
-					self::$_usedBackends[$backend] = new $className();
105
-					\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
106
-					break;
107
-			}
108
-		}
109
-		return true;
110
-	}
111
-
112
-	/**
113
-	 * remove all used backends
114
-	 */
115
-	public static function clearBackends() {
116
-		self::$_usedBackends = [];
117
-		\OC::$server->getUserManager()->clearBackends();
118
-	}
119
-
120
-	/**
121
-	 * setup the configured backends in config.php
122
-	 * @suppress PhanDeprecatedFunction
123
-	 */
124
-	public static function setupBackends() {
125
-		OC_App::loadApps(['prelogin']);
126
-		$backends = \OC::$server->getSystemConfig()->getValue('user_backends', []);
127
-		if (isset($backends['default']) && !$backends['default']) {
128
-			// clear default backends
129
-			self::clearBackends();
130
-		}
131
-		foreach ($backends as $i => $config) {
132
-			if (!is_array($config)) {
133
-				continue;
134
-			}
135
-			$class = $config['class'];
136
-			$arguments = $config['arguments'];
137
-			if (class_exists($class)) {
138
-				if (array_search($i, self::$_setupedBackends) === false) {
139
-					// make a reflection object
140
-					$reflectionObj = new ReflectionClass($class);
141
-
142
-					// use Reflection to create a new instance, using the $args
143
-					$backend = $reflectionObj->newInstanceArgs($arguments);
144
-					self::useBackend($backend);
145
-					self::$_setupedBackends[] = $i;
146
-				} else {
147
-					\OCP\Util::writeLog('core', 'User backend ' . $class . ' already initialized.', ILogger::DEBUG);
148
-				}
149
-			} else {
150
-				\OCP\Util::writeLog('core', 'User backend ' . $class . ' not found.', ILogger::ERROR);
151
-			}
152
-		}
153
-	}
154
-
155
-	/**
156
-	 * Try to login a user, assuming authentication
157
-	 * has already happened (e.g. via Single Sign On).
158
-	 *
159
-	 * Log in a user and regenerate a new session.
160
-	 *
161
-	 * @param \OCP\Authentication\IApacheBackend $backend
162
-	 * @return bool
163
-	 */
164
-	public static function loginWithApache(\OCP\Authentication\IApacheBackend $backend) {
165
-
166
-		$uid = $backend->getCurrentUserId();
167
-		$run = true;
168
-		OC_Hook::emit("OC_User", "pre_login", ["run" => &$run, "uid" => $uid, 'backend' => $backend]);
169
-
170
-		if ($uid) {
171
-			if (self::getUser() !== $uid) {
172
-				self::setUserId($uid);
173
-				$userSession = \OC::$server->getUserSession();
174
-				$userSession->setLoginName($uid);
175
-				$request = OC::$server->getRequest();
176
-				$userSession->createSessionToken($request, $uid, $uid);
177
-				// setup the filesystem
178
-				OC_Util::setupFS($uid);
179
-				// first call the post_login hooks, the login-process needs to be
180
-				// completed before we can safely create the users folder.
181
-				// For example encryption needs to initialize the users keys first
182
-				// before we can create the user folder with the skeleton files
183
-				OC_Hook::emit(
184
-					'OC_User',
185
-					'post_login',
186
-					[
187
-						'uid' => $uid,
188
-						'password' => '',
189
-						'isTokenLogin' => false,
190
-					]
191
-				);
192
-				//trigger creation of user home and /files folder
193
-				\OC::$server->getUserFolder($uid);
194
-			}
195
-			return true;
196
-		}
197
-		return false;
198
-	}
199
-
200
-	/**
201
-	 * Verify with Apache whether user is authenticated.
202
-	 *
203
-	 * @return boolean|null
204
-	 *          true: authenticated
205
-	 *          false: not authenticated
206
-	 *          null: not handled / no backend available
207
-	 */
208
-	public static function handleApacheAuth() {
209
-		$backend = self::findFirstActiveUsedBackend();
210
-		if ($backend) {
211
-			OC_App::loadApps();
212
-
213
-			//setup extra user backends
214
-			self::setupBackends();
215
-			\OC::$server->getUserSession()->unsetMagicInCookie();
216
-
217
-			return self::loginWithApache($backend);
218
-		}
219
-
220
-		return null;
221
-	}
222
-
223
-
224
-	/**
225
-	 * Sets user id for session and triggers emit
226
-	 *
227
-	 * @param string $uid
228
-	 */
229
-	public static function setUserId($uid) {
230
-		$userSession = \OC::$server->getUserSession();
231
-		$userManager = \OC::$server->getUserManager();
232
-		if ($user = $userManager->get($uid)) {
233
-			$userSession->setUser($user);
234
-		} else {
235
-			\OC::$server->getSession()->set('user_id', $uid);
236
-		}
237
-	}
238
-
239
-	/**
240
-	 * Check if the user is logged in, considers also the HTTP basic credentials
241
-	 *
242
-	 * @deprecated use \OC::$server->getUserSession()->isLoggedIn()
243
-	 * @return bool
244
-	 */
245
-	public static function isLoggedIn() {
246
-		return \OC::$server->getUserSession()->isLoggedIn();
247
-	}
248
-
249
-	/**
250
-	 * set incognito mode, e.g. if a user wants to open a public link
251
-	 *
252
-	 * @param bool $status
253
-	 */
254
-	public static function setIncognitoMode($status) {
255
-		self::$incognitoMode = $status;
256
-	}
257
-
258
-	/**
259
-	 * get incognito mode status
260
-	 *
261
-	 * @return bool
262
-	 */
263
-	public static function isIncognitoMode() {
264
-		return self::$incognitoMode;
265
-	}
266
-
267
-	/**
268
-	 * Returns the current logout URL valid for the currently logged-in user
269
-	 *
270
-	 * @param \OCP\IURLGenerator $urlGenerator
271
-	 * @return string
272
-	 */
273
-	public static function getLogoutUrl(\OCP\IURLGenerator $urlGenerator) {
274
-		$backend = self::findFirstActiveUsedBackend();
275
-		if ($backend) {
276
-			return $backend->getLogoutUrl();
277
-		}
278
-
279
-		$logoutUrl = $urlGenerator->linkToRoute('core.login.logout');
280
-		$logoutUrl .= '?requesttoken=' . urlencode(\OCP\Util::callRegister());
281
-
282
-		return $logoutUrl;
283
-	}
284
-
285
-	/**
286
-	 * Check if the user is an admin user
287
-	 *
288
-	 * @param string $uid uid of the admin
289
-	 * @return bool
290
-	 */
291
-	public static function isAdminUser($uid) {
292
-		$group = \OC::$server->getGroupManager()->get('admin');
293
-		$user = \OC::$server->getUserManager()->get($uid);
294
-		if ($group && $user && $group->inGroup($user) && self::$incognitoMode === false) {
295
-			return true;
296
-		}
297
-		return false;
298
-	}
299
-
300
-
301
-	/**
302
-	 * get the user id of the user currently logged in.
303
-	 *
304
-	 * @return string|bool uid or false
305
-	 */
306
-	public static function getUser() {
307
-		$uid = \OC::$server->getSession() ? \OC::$server->getSession()->get('user_id') : null;
308
-		if (!is_null($uid) && self::$incognitoMode === false) {
309
-			return $uid;
310
-		} else {
311
-			return false;
312
-		}
313
-	}
314
-
315
-	/**
316
-	 * get the display name of the user currently logged in.
317
-	 *
318
-	 * @param string $uid
319
-	 * @return string|bool uid or false
320
-	 * @deprecated 8.1.0 fetch \OCP\IUser (has getDisplayName()) by using method
321
-	 *                   get() of \OCP\IUserManager - \OC::$server->getUserManager()
322
-	 */
323
-	public static function getDisplayName($uid = null) {
324
-		if ($uid) {
325
-			$user = \OC::$server->getUserManager()->get($uid);
326
-			if ($user) {
327
-				return $user->getDisplayName();
328
-			} else {
329
-				return $uid;
330
-			}
331
-		} else {
332
-			$user = \OC::$server->getUserSession()->getUser();
333
-			if ($user) {
334
-				return $user->getDisplayName();
335
-			} else {
336
-				return false;
337
-			}
338
-		}
339
-	}
340
-
341
-	/**
342
-	 * Set password
343
-	 *
344
-	 * @param string $uid The username
345
-	 * @param string $password The new password
346
-	 * @param string $recoveryPassword for the encryption app to reset encryption keys
347
-	 * @return bool
348
-	 *
349
-	 * Change the password of a user
350
-	 */
351
-	public static function setPassword($uid, $password, $recoveryPassword = null) {
352
-		$user = \OC::$server->getUserManager()->get($uid);
353
-		if ($user) {
354
-			return $user->setPassword($password, $recoveryPassword);
355
-		} else {
356
-			return false;
357
-		}
358
-	}
359
-
360
-	/**
361
-	 * @param string $uid The username
362
-	 * @return string
363
-	 *
364
-	 * returns the path to the users home directory
365
-	 * @deprecated Use \OC::$server->getUserManager->getHome()
366
-	 */
367
-	public static function getHome($uid) {
368
-		$user = \OC::$server->getUserManager()->get($uid);
369
-		if ($user) {
370
-			return $user->getHome();
371
-		} else {
372
-			return \OC::$server->getSystemConfig()->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid;
373
-		}
374
-	}
375
-
376
-	/**
377
-	 * Get a list of all users display name
378
-	 *
379
-	 * @param string $search
380
-	 * @param int $limit
381
-	 * @param int $offset
382
-	 * @return array associative array with all display names (value) and corresponding uids (key)
383
-	 *
384
-	 * Get a list of all display names and user ids.
385
-	 * @deprecated Use \OC::$server->getUserManager->searchDisplayName($search, $limit, $offset) instead.
386
-	 */
387
-	public static function getDisplayNames($search = '', $limit = null, $offset = null) {
388
-		$displayNames = [];
389
-		$users = \OC::$server->getUserManager()->searchDisplayName($search, $limit, $offset);
390
-		foreach ($users as $user) {
391
-			$displayNames[$user->getUID()] = $user->getDisplayName();
392
-		}
393
-		return $displayNames;
394
-	}
395
-
396
-	/**
397
-	 * Returns the first active backend from self::$_usedBackends.
398
-	 *
399
-	 * @return OCP\Authentication\IApacheBackend|null if no backend active, otherwise OCP\Authentication\IApacheBackend
400
-	 */
401
-	private static function findFirstActiveUsedBackend() {
402
-		foreach (self::$_usedBackends as $backend) {
403
-			if ($backend instanceof OCP\Authentication\IApacheBackend) {
404
-				if ($backend->isSessionActive()) {
405
-					return $backend;
406
-				}
407
-			}
408
-		}
409
-
410
-		return null;
411
-	}
62
+    private static $_usedBackends = [];
63
+
64
+    private static $_setupedBackends = [];
65
+
66
+    // bool, stores if a user want to access a resource anonymously, e.g if they open a public link
67
+    private static $incognitoMode = false;
68
+
69
+    /**
70
+     * Adds the backend to the list of used backends
71
+     *
72
+     * @param string|\OCP\UserInterface $backend default: database The backend to use for user management
73
+     * @return bool
74
+     *
75
+     * Set the User Authentication Module
76
+     * @suppress PhanDeprecatedFunction
77
+     */
78
+    public static function useBackend($backend = 'database') {
79
+        if ($backend instanceof \OCP\UserInterface) {
80
+            self::$_usedBackends[get_class($backend)] = $backend;
81
+            \OC::$server->getUserManager()->registerBackend($backend);
82
+        } else {
83
+            // You'll never know what happens
84
+            if (null === $backend OR !is_string($backend)) {
85
+                $backend = 'database';
86
+            }
87
+
88
+            // Load backend
89
+            switch ($backend) {
90
+                case 'database':
91
+                case 'mysql':
92
+                case 'sqlite':
93
+                    \OCP\Util::writeLog('core', 'Adding user backend ' . $backend . '.', ILogger::DEBUG);
94
+                    self::$_usedBackends[$backend] = new \OC\User\Database();
95
+                    \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
96
+                    break;
97
+                case 'dummy':
98
+                    self::$_usedBackends[$backend] = new \Test\Util\User\Dummy();
99
+                    \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
100
+                    break;
101
+                default:
102
+                    \OCP\Util::writeLog('core', 'Adding default user backend ' . $backend . '.', ILogger::DEBUG);
103
+                    $className = 'OC_USER_' . strtoupper($backend);
104
+                    self::$_usedBackends[$backend] = new $className();
105
+                    \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
106
+                    break;
107
+            }
108
+        }
109
+        return true;
110
+    }
111
+
112
+    /**
113
+     * remove all used backends
114
+     */
115
+    public static function clearBackends() {
116
+        self::$_usedBackends = [];
117
+        \OC::$server->getUserManager()->clearBackends();
118
+    }
119
+
120
+    /**
121
+     * setup the configured backends in config.php
122
+     * @suppress PhanDeprecatedFunction
123
+     */
124
+    public static function setupBackends() {
125
+        OC_App::loadApps(['prelogin']);
126
+        $backends = \OC::$server->getSystemConfig()->getValue('user_backends', []);
127
+        if (isset($backends['default']) && !$backends['default']) {
128
+            // clear default backends
129
+            self::clearBackends();
130
+        }
131
+        foreach ($backends as $i => $config) {
132
+            if (!is_array($config)) {
133
+                continue;
134
+            }
135
+            $class = $config['class'];
136
+            $arguments = $config['arguments'];
137
+            if (class_exists($class)) {
138
+                if (array_search($i, self::$_setupedBackends) === false) {
139
+                    // make a reflection object
140
+                    $reflectionObj = new ReflectionClass($class);
141
+
142
+                    // use Reflection to create a new instance, using the $args
143
+                    $backend = $reflectionObj->newInstanceArgs($arguments);
144
+                    self::useBackend($backend);
145
+                    self::$_setupedBackends[] = $i;
146
+                } else {
147
+                    \OCP\Util::writeLog('core', 'User backend ' . $class . ' already initialized.', ILogger::DEBUG);
148
+                }
149
+            } else {
150
+                \OCP\Util::writeLog('core', 'User backend ' . $class . ' not found.', ILogger::ERROR);
151
+            }
152
+        }
153
+    }
154
+
155
+    /**
156
+     * Try to login a user, assuming authentication
157
+     * has already happened (e.g. via Single Sign On).
158
+     *
159
+     * Log in a user and regenerate a new session.
160
+     *
161
+     * @param \OCP\Authentication\IApacheBackend $backend
162
+     * @return bool
163
+     */
164
+    public static function loginWithApache(\OCP\Authentication\IApacheBackend $backend) {
165
+
166
+        $uid = $backend->getCurrentUserId();
167
+        $run = true;
168
+        OC_Hook::emit("OC_User", "pre_login", ["run" => &$run, "uid" => $uid, 'backend' => $backend]);
169
+
170
+        if ($uid) {
171
+            if (self::getUser() !== $uid) {
172
+                self::setUserId($uid);
173
+                $userSession = \OC::$server->getUserSession();
174
+                $userSession->setLoginName($uid);
175
+                $request = OC::$server->getRequest();
176
+                $userSession->createSessionToken($request, $uid, $uid);
177
+                // setup the filesystem
178
+                OC_Util::setupFS($uid);
179
+                // first call the post_login hooks, the login-process needs to be
180
+                // completed before we can safely create the users folder.
181
+                // For example encryption needs to initialize the users keys first
182
+                // before we can create the user folder with the skeleton files
183
+                OC_Hook::emit(
184
+                    'OC_User',
185
+                    'post_login',
186
+                    [
187
+                        'uid' => $uid,
188
+                        'password' => '',
189
+                        'isTokenLogin' => false,
190
+                    ]
191
+                );
192
+                //trigger creation of user home and /files folder
193
+                \OC::$server->getUserFolder($uid);
194
+            }
195
+            return true;
196
+        }
197
+        return false;
198
+    }
199
+
200
+    /**
201
+     * Verify with Apache whether user is authenticated.
202
+     *
203
+     * @return boolean|null
204
+     *          true: authenticated
205
+     *          false: not authenticated
206
+     *          null: not handled / no backend available
207
+     */
208
+    public static function handleApacheAuth() {
209
+        $backend = self::findFirstActiveUsedBackend();
210
+        if ($backend) {
211
+            OC_App::loadApps();
212
+
213
+            //setup extra user backends
214
+            self::setupBackends();
215
+            \OC::$server->getUserSession()->unsetMagicInCookie();
216
+
217
+            return self::loginWithApache($backend);
218
+        }
219
+
220
+        return null;
221
+    }
222
+
223
+
224
+    /**
225
+     * Sets user id for session and triggers emit
226
+     *
227
+     * @param string $uid
228
+     */
229
+    public static function setUserId($uid) {
230
+        $userSession = \OC::$server->getUserSession();
231
+        $userManager = \OC::$server->getUserManager();
232
+        if ($user = $userManager->get($uid)) {
233
+            $userSession->setUser($user);
234
+        } else {
235
+            \OC::$server->getSession()->set('user_id', $uid);
236
+        }
237
+    }
238
+
239
+    /**
240
+     * Check if the user is logged in, considers also the HTTP basic credentials
241
+     *
242
+     * @deprecated use \OC::$server->getUserSession()->isLoggedIn()
243
+     * @return bool
244
+     */
245
+    public static function isLoggedIn() {
246
+        return \OC::$server->getUserSession()->isLoggedIn();
247
+    }
248
+
249
+    /**
250
+     * set incognito mode, e.g. if a user wants to open a public link
251
+     *
252
+     * @param bool $status
253
+     */
254
+    public static function setIncognitoMode($status) {
255
+        self::$incognitoMode = $status;
256
+    }
257
+
258
+    /**
259
+     * get incognito mode status
260
+     *
261
+     * @return bool
262
+     */
263
+    public static function isIncognitoMode() {
264
+        return self::$incognitoMode;
265
+    }
266
+
267
+    /**
268
+     * Returns the current logout URL valid for the currently logged-in user
269
+     *
270
+     * @param \OCP\IURLGenerator $urlGenerator
271
+     * @return string
272
+     */
273
+    public static function getLogoutUrl(\OCP\IURLGenerator $urlGenerator) {
274
+        $backend = self::findFirstActiveUsedBackend();
275
+        if ($backend) {
276
+            return $backend->getLogoutUrl();
277
+        }
278
+
279
+        $logoutUrl = $urlGenerator->linkToRoute('core.login.logout');
280
+        $logoutUrl .= '?requesttoken=' . urlencode(\OCP\Util::callRegister());
281
+
282
+        return $logoutUrl;
283
+    }
284
+
285
+    /**
286
+     * Check if the user is an admin user
287
+     *
288
+     * @param string $uid uid of the admin
289
+     * @return bool
290
+     */
291
+    public static function isAdminUser($uid) {
292
+        $group = \OC::$server->getGroupManager()->get('admin');
293
+        $user = \OC::$server->getUserManager()->get($uid);
294
+        if ($group && $user && $group->inGroup($user) && self::$incognitoMode === false) {
295
+            return true;
296
+        }
297
+        return false;
298
+    }
299
+
300
+
301
+    /**
302
+     * get the user id of the user currently logged in.
303
+     *
304
+     * @return string|bool uid or false
305
+     */
306
+    public static function getUser() {
307
+        $uid = \OC::$server->getSession() ? \OC::$server->getSession()->get('user_id') : null;
308
+        if (!is_null($uid) && self::$incognitoMode === false) {
309
+            return $uid;
310
+        } else {
311
+            return false;
312
+        }
313
+    }
314
+
315
+    /**
316
+     * get the display name of the user currently logged in.
317
+     *
318
+     * @param string $uid
319
+     * @return string|bool uid or false
320
+     * @deprecated 8.1.0 fetch \OCP\IUser (has getDisplayName()) by using method
321
+     *                   get() of \OCP\IUserManager - \OC::$server->getUserManager()
322
+     */
323
+    public static function getDisplayName($uid = null) {
324
+        if ($uid) {
325
+            $user = \OC::$server->getUserManager()->get($uid);
326
+            if ($user) {
327
+                return $user->getDisplayName();
328
+            } else {
329
+                return $uid;
330
+            }
331
+        } else {
332
+            $user = \OC::$server->getUserSession()->getUser();
333
+            if ($user) {
334
+                return $user->getDisplayName();
335
+            } else {
336
+                return false;
337
+            }
338
+        }
339
+    }
340
+
341
+    /**
342
+     * Set password
343
+     *
344
+     * @param string $uid The username
345
+     * @param string $password The new password
346
+     * @param string $recoveryPassword for the encryption app to reset encryption keys
347
+     * @return bool
348
+     *
349
+     * Change the password of a user
350
+     */
351
+    public static function setPassword($uid, $password, $recoveryPassword = null) {
352
+        $user = \OC::$server->getUserManager()->get($uid);
353
+        if ($user) {
354
+            return $user->setPassword($password, $recoveryPassword);
355
+        } else {
356
+            return false;
357
+        }
358
+    }
359
+
360
+    /**
361
+     * @param string $uid The username
362
+     * @return string
363
+     *
364
+     * returns the path to the users home directory
365
+     * @deprecated Use \OC::$server->getUserManager->getHome()
366
+     */
367
+    public static function getHome($uid) {
368
+        $user = \OC::$server->getUserManager()->get($uid);
369
+        if ($user) {
370
+            return $user->getHome();
371
+        } else {
372
+            return \OC::$server->getSystemConfig()->getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid;
373
+        }
374
+    }
375
+
376
+    /**
377
+     * Get a list of all users display name
378
+     *
379
+     * @param string $search
380
+     * @param int $limit
381
+     * @param int $offset
382
+     * @return array associative array with all display names (value) and corresponding uids (key)
383
+     *
384
+     * Get a list of all display names and user ids.
385
+     * @deprecated Use \OC::$server->getUserManager->searchDisplayName($search, $limit, $offset) instead.
386
+     */
387
+    public static function getDisplayNames($search = '', $limit = null, $offset = null) {
388
+        $displayNames = [];
389
+        $users = \OC::$server->getUserManager()->searchDisplayName($search, $limit, $offset);
390
+        foreach ($users as $user) {
391
+            $displayNames[$user->getUID()] = $user->getDisplayName();
392
+        }
393
+        return $displayNames;
394
+    }
395
+
396
+    /**
397
+     * Returns the first active backend from self::$_usedBackends.
398
+     *
399
+     * @return OCP\Authentication\IApacheBackend|null if no backend active, otherwise OCP\Authentication\IApacheBackend
400
+     */
401
+    private static function findFirstActiveUsedBackend() {
402
+        foreach (self::$_usedBackends as $backend) {
403
+            if ($backend instanceof OCP\Authentication\IApacheBackend) {
404
+                if ($backend->isSessionActive()) {
405
+                    return $backend;
406
+                }
407
+            }
408
+        }
409
+
410
+        return null;
411
+    }
412 412
 }
Please login to merge, or discard this patch.
lib/private/legacy/db.php 1 patch
Indentation   +193 added lines, -193 removed lines patch added patch discarded remove patch
@@ -37,209 +37,209 @@
 block discarded – undo
37 37
  */
38 38
 class OC_DB {
39 39
 
40
-	/**
41
-	 * get MDB2 schema manager
42
-	 *
43
-	 * @return \OC\DB\MDB2SchemaManager
44
-	 */
45
-	private static function getMDB2SchemaManager() {
46
-		return new \OC\DB\MDB2SchemaManager(\OC::$server->getDatabaseConnection());
47
-	}
40
+    /**
41
+     * get MDB2 schema manager
42
+     *
43
+     * @return \OC\DB\MDB2SchemaManager
44
+     */
45
+    private static function getMDB2SchemaManager() {
46
+        return new \OC\DB\MDB2SchemaManager(\OC::$server->getDatabaseConnection());
47
+    }
48 48
 
49
-	/**
50
-	 * Prepare a SQL query
51
-	 * @param string $query Query string
52
-	 * @param int|null $limit
53
-	 * @param int|null $offset
54
-	 * @param bool|null $isManipulation
55
-	 * @throws \OC\DatabaseException
56
-	 * @return OC_DB_StatementWrapper prepared SQL query
57
-	 *
58
-	 * SQL query via Doctrine prepare(), needs to be execute()'d!
59
-	 */
60
-	static public function prepare( $query , $limit = null, $offset = null, $isManipulation = null) {
61
-		$connection = \OC::$server->getDatabaseConnection();
49
+    /**
50
+     * Prepare a SQL query
51
+     * @param string $query Query string
52
+     * @param int|null $limit
53
+     * @param int|null $offset
54
+     * @param bool|null $isManipulation
55
+     * @throws \OC\DatabaseException
56
+     * @return OC_DB_StatementWrapper prepared SQL query
57
+     *
58
+     * SQL query via Doctrine prepare(), needs to be execute()'d!
59
+     */
60
+    static public function prepare( $query , $limit = null, $offset = null, $isManipulation = null) {
61
+        $connection = \OC::$server->getDatabaseConnection();
62 62
 
63
-		if ($isManipulation === null) {
64
-			//try to guess, so we return the number of rows on manipulations
65
-			$isManipulation = self::isManipulation($query);
66
-		}
63
+        if ($isManipulation === null) {
64
+            //try to guess, so we return the number of rows on manipulations
65
+            $isManipulation = self::isManipulation($query);
66
+        }
67 67
 
68
-		// return the result
69
-		try {
70
-			$result =$connection->prepare($query, $limit, $offset);
71
-		} catch (\Doctrine\DBAL\DBALException $e) {
72
-			throw new \OC\DatabaseException($e->getMessage());
73
-		}
74
-		// differentiate between query and manipulation
75
-		$result = new OC_DB_StatementWrapper($result, $isManipulation);
76
-		return $result;
77
-	}
68
+        // return the result
69
+        try {
70
+            $result =$connection->prepare($query, $limit, $offset);
71
+        } catch (\Doctrine\DBAL\DBALException $e) {
72
+            throw new \OC\DatabaseException($e->getMessage());
73
+        }
74
+        // differentiate between query and manipulation
75
+        $result = new OC_DB_StatementWrapper($result, $isManipulation);
76
+        return $result;
77
+    }
78 78
 
79
-	/**
80
-	 * tries to guess the type of statement based on the first 10 characters
81
-	 * the current check allows some whitespace but does not work with IF EXISTS or other more complex statements
82
-	 *
83
-	 * @param string $sql
84
-	 * @return bool
85
-	 */
86
-	static public function isManipulation( $sql ) {
87
-		$selectOccurrence = stripos($sql, 'SELECT');
88
-		if ($selectOccurrence !== false && $selectOccurrence < 10) {
89
-			return false;
90
-		}
91
-		$insertOccurrence = stripos($sql, 'INSERT');
92
-		if ($insertOccurrence !== false && $insertOccurrence < 10) {
93
-			return true;
94
-		}
95
-		$updateOccurrence = stripos($sql, 'UPDATE');
96
-		if ($updateOccurrence !== false && $updateOccurrence < 10) {
97
-			return true;
98
-		}
99
-		$deleteOccurrence = stripos($sql, 'DELETE');
100
-		if ($deleteOccurrence !== false && $deleteOccurrence < 10) {
101
-			return true;
102
-		}
103
-		return false;
104
-	}
79
+    /**
80
+     * tries to guess the type of statement based on the first 10 characters
81
+     * the current check allows some whitespace but does not work with IF EXISTS or other more complex statements
82
+     *
83
+     * @param string $sql
84
+     * @return bool
85
+     */
86
+    static public function isManipulation( $sql ) {
87
+        $selectOccurrence = stripos($sql, 'SELECT');
88
+        if ($selectOccurrence !== false && $selectOccurrence < 10) {
89
+            return false;
90
+        }
91
+        $insertOccurrence = stripos($sql, 'INSERT');
92
+        if ($insertOccurrence !== false && $insertOccurrence < 10) {
93
+            return true;
94
+        }
95
+        $updateOccurrence = stripos($sql, 'UPDATE');
96
+        if ($updateOccurrence !== false && $updateOccurrence < 10) {
97
+            return true;
98
+        }
99
+        $deleteOccurrence = stripos($sql, 'DELETE');
100
+        if ($deleteOccurrence !== false && $deleteOccurrence < 10) {
101
+            return true;
102
+        }
103
+        return false;
104
+    }
105 105
 
106
-	/**
107
-	 * execute a prepared statement, on error write log and throw exception
108
-	 * @param mixed $stmt OC_DB_StatementWrapper,
109
-	 *					  an array with 'sql' and optionally 'limit' and 'offset' keys
110
-	 *					.. or a simple sql query string
111
-	 * @param array $parameters
112
-	 * @return OC_DB_StatementWrapper
113
-	 * @throws \OC\DatabaseException
114
-	 */
115
-	static public function executeAudited( $stmt, array $parameters = []) {
116
-		if (is_string($stmt)) {
117
-			// convert to an array with 'sql'
118
-			if (stripos($stmt, 'LIMIT') !== false) { //OFFSET requires LIMIT, so we only need to check for LIMIT
119
-				// TODO try to convert LIMIT OFFSET notation to parameters
120
-				$message = 'LIMIT and OFFSET are forbidden for portability reasons,'
121
-						 . ' pass an array with \'limit\' and \'offset\' instead';
122
-				throw new \OC\DatabaseException($message);
123
-			}
124
-			$stmt = ['sql' => $stmt, 'limit' => null, 'offset' => null];
125
-		}
126
-		if (is_array($stmt)) {
127
-			// convert to prepared statement
128
-			if ( ! array_key_exists('sql', $stmt) ) {
129
-				$message = 'statement array must at least contain key \'sql\'';
130
-				throw new \OC\DatabaseException($message);
131
-			}
132
-			if ( ! array_key_exists('limit', $stmt) ) {
133
-				$stmt['limit'] = null;
134
-			}
135
-			if ( ! array_key_exists('limit', $stmt) ) {
136
-				$stmt['offset'] = null;
137
-			}
138
-			$stmt = self::prepare($stmt['sql'], $stmt['limit'], $stmt['offset']);
139
-		}
140
-		self::raiseExceptionOnError($stmt, 'Could not prepare statement');
141
-		if ($stmt instanceof OC_DB_StatementWrapper) {
142
-			$result = $stmt->execute($parameters);
143
-			self::raiseExceptionOnError($result, 'Could not execute statement');
144
-		} else {
145
-			if (is_object($stmt)) {
146
-				$message = 'Expected a prepared statement or array got ' . get_class($stmt);
147
-			} else {
148
-				$message = 'Expected a prepared statement or array got ' . gettype($stmt);
149
-			}
150
-			throw new \OC\DatabaseException($message);
151
-		}
152
-		return $result;
153
-	}
106
+    /**
107
+     * execute a prepared statement, on error write log and throw exception
108
+     * @param mixed $stmt OC_DB_StatementWrapper,
109
+     *					  an array with 'sql' and optionally 'limit' and 'offset' keys
110
+     *					.. or a simple sql query string
111
+     * @param array $parameters
112
+     * @return OC_DB_StatementWrapper
113
+     * @throws \OC\DatabaseException
114
+     */
115
+    static public function executeAudited( $stmt, array $parameters = []) {
116
+        if (is_string($stmt)) {
117
+            // convert to an array with 'sql'
118
+            if (stripos($stmt, 'LIMIT') !== false) { //OFFSET requires LIMIT, so we only need to check for LIMIT
119
+                // TODO try to convert LIMIT OFFSET notation to parameters
120
+                $message = 'LIMIT and OFFSET are forbidden for portability reasons,'
121
+                            . ' pass an array with \'limit\' and \'offset\' instead';
122
+                throw new \OC\DatabaseException($message);
123
+            }
124
+            $stmt = ['sql' => $stmt, 'limit' => null, 'offset' => null];
125
+        }
126
+        if (is_array($stmt)) {
127
+            // convert to prepared statement
128
+            if ( ! array_key_exists('sql', $stmt) ) {
129
+                $message = 'statement array must at least contain key \'sql\'';
130
+                throw new \OC\DatabaseException($message);
131
+            }
132
+            if ( ! array_key_exists('limit', $stmt) ) {
133
+                $stmt['limit'] = null;
134
+            }
135
+            if ( ! array_key_exists('limit', $stmt) ) {
136
+                $stmt['offset'] = null;
137
+            }
138
+            $stmt = self::prepare($stmt['sql'], $stmt['limit'], $stmt['offset']);
139
+        }
140
+        self::raiseExceptionOnError($stmt, 'Could not prepare statement');
141
+        if ($stmt instanceof OC_DB_StatementWrapper) {
142
+            $result = $stmt->execute($parameters);
143
+            self::raiseExceptionOnError($result, 'Could not execute statement');
144
+        } else {
145
+            if (is_object($stmt)) {
146
+                $message = 'Expected a prepared statement or array got ' . get_class($stmt);
147
+            } else {
148
+                $message = 'Expected a prepared statement or array got ' . gettype($stmt);
149
+            }
150
+            throw new \OC\DatabaseException($message);
151
+        }
152
+        return $result;
153
+    }
154 154
 
155
-	/**
156
-	 * saves database schema to xml file
157
-	 * @param string $file name of file
158
-	 * @return bool
159
-	 *
160
-	 * TODO: write more documentation
161
-	 */
162
-	public static function getDbStructure($file) {
163
-		$schemaManager = self::getMDB2SchemaManager();
164
-		return $schemaManager->getDbStructure($file);
165
-	}
155
+    /**
156
+     * saves database schema to xml file
157
+     * @param string $file name of file
158
+     * @return bool
159
+     *
160
+     * TODO: write more documentation
161
+     */
162
+    public static function getDbStructure($file) {
163
+        $schemaManager = self::getMDB2SchemaManager();
164
+        return $schemaManager->getDbStructure($file);
165
+    }
166 166
 
167
-	/**
168
-	 * Creates tables from XML file
169
-	 * @param string $file file to read structure from
170
-	 * @return bool
171
-	 *
172
-	 * TODO: write more documentation
173
-	 */
174
-	public static function createDbFromStructure( $file ) {
175
-		$schemaManager = self::getMDB2SchemaManager();
176
-		return $schemaManager->createDbFromStructure($file);
177
-	}
167
+    /**
168
+     * Creates tables from XML file
169
+     * @param string $file file to read structure from
170
+     * @return bool
171
+     *
172
+     * TODO: write more documentation
173
+     */
174
+    public static function createDbFromStructure( $file ) {
175
+        $schemaManager = self::getMDB2SchemaManager();
176
+        return $schemaManager->createDbFromStructure($file);
177
+    }
178 178
 
179
-	/**
180
-	 * update the database schema
181
-	 * @param string $file file to read structure from
182
-	 * @throws Exception
183
-	 * @return string|boolean
184
-	 * @suppress PhanDeprecatedFunction
185
-	 */
186
-	public static function updateDbFromStructure($file) {
187
-		$schemaManager = self::getMDB2SchemaManager();
188
-		try {
189
-			$result = $schemaManager->updateDbFromStructure($file);
190
-		} catch (Exception $e) {
191
-			\OCP\Util::writeLog('core', 'Failed to update database structure ('.$e.')', ILogger::FATAL);
192
-			throw $e;
193
-		}
194
-		return $result;
195
-	}
179
+    /**
180
+     * update the database schema
181
+     * @param string $file file to read structure from
182
+     * @throws Exception
183
+     * @return string|boolean
184
+     * @suppress PhanDeprecatedFunction
185
+     */
186
+    public static function updateDbFromStructure($file) {
187
+        $schemaManager = self::getMDB2SchemaManager();
188
+        try {
189
+            $result = $schemaManager->updateDbFromStructure($file);
190
+        } catch (Exception $e) {
191
+            \OCP\Util::writeLog('core', 'Failed to update database structure ('.$e.')', ILogger::FATAL);
192
+            throw $e;
193
+        }
194
+        return $result;
195
+    }
196 196
 
197
-	/**
198
-	 * remove all tables defined in a database structure xml file
199
-	 * @param string $file the xml file describing the tables
200
-	 */
201
-	public static function removeDBStructure($file) {
202
-		$schemaManager = self::getMDB2SchemaManager();
203
-		$schemaManager->removeDBStructure($file);
204
-	}
197
+    /**
198
+     * remove all tables defined in a database structure xml file
199
+     * @param string $file the xml file describing the tables
200
+     */
201
+    public static function removeDBStructure($file) {
202
+        $schemaManager = self::getMDB2SchemaManager();
203
+        $schemaManager->removeDBStructure($file);
204
+    }
205 205
 
206
-	/**
207
-	 * check if a result is an error and throws an exception, works with \Doctrine\DBAL\DBALException
208
-	 * @param mixed $result
209
-	 * @param string $message
210
-	 * @return void
211
-	 * @throws \OC\DatabaseException
212
-	 */
213
-	public static function raiseExceptionOnError($result, $message = null) {
214
-		if($result === false) {
215
-			if ($message === null) {
216
-				$message = self::getErrorMessage();
217
-			} else {
218
-				$message .= ', Root cause:' . self::getErrorMessage();
219
-			}
220
-			throw new \OC\DatabaseException($message);
221
-		}
222
-	}
206
+    /**
207
+     * check if a result is an error and throws an exception, works with \Doctrine\DBAL\DBALException
208
+     * @param mixed $result
209
+     * @param string $message
210
+     * @return void
211
+     * @throws \OC\DatabaseException
212
+     */
213
+    public static function raiseExceptionOnError($result, $message = null) {
214
+        if($result === false) {
215
+            if ($message === null) {
216
+                $message = self::getErrorMessage();
217
+            } else {
218
+                $message .= ', Root cause:' . self::getErrorMessage();
219
+            }
220
+            throw new \OC\DatabaseException($message);
221
+        }
222
+    }
223 223
 
224
-	/**
225
-	 * returns the error code and message as a string for logging
226
-	 * works with DoctrineException
227
-	 * @return string
228
-	 */
229
-	public static function getErrorMessage() {
230
-		$connection = \OC::$server->getDatabaseConnection();
231
-		return $connection->getError();
232
-	}
224
+    /**
225
+     * returns the error code and message as a string for logging
226
+     * works with DoctrineException
227
+     * @return string
228
+     */
229
+    public static function getErrorMessage() {
230
+        $connection = \OC::$server->getDatabaseConnection();
231
+        return $connection->getError();
232
+    }
233 233
 
234
-	/**
235
-	 * Checks if a table exists in the database - the database prefix will be prepended
236
-	 *
237
-	 * @param string $table
238
-	 * @return bool
239
-	 * @throws \OC\DatabaseException
240
-	 */
241
-	public static function tableExists($table) {
242
-		$connection = \OC::$server->getDatabaseConnection();
243
-		return $connection->tableExists($table);
244
-	}
234
+    /**
235
+     * Checks if a table exists in the database - the database prefix will be prepended
236
+     *
237
+     * @param string $table
238
+     * @return bool
239
+     * @throws \OC\DatabaseException
240
+     */
241
+    public static function tableExists($table) {
242
+        $connection = \OC::$server->getDatabaseConnection();
243
+        return $connection->tableExists($table);
244
+    }
245 245
 }
Please login to merge, or discard this patch.
lib/private/legacy/json.php 1 patch
Indentation   +94 added lines, -94 removed lines patch added patch discarded remove patch
@@ -35,106 +35,106 @@
 block discarded – undo
35 35
  */
36 36
 class OC_JSON{
37 37
 
38
-	/**
39
-	 * Check if the app is enabled, send json error msg if not
40
-	 * @param string $app
41
-	 * @deprecated Use the AppFramework instead. It will automatically check if the app is enabled.
42
-	 * @suppress PhanDeprecatedFunction
43
-	 */
44
-	public static function checkAppEnabled($app) {
45
-		if( !\OC::$server->getAppManager()->isEnabledForUser($app)) {
46
-			$l = \OC::$server->getL10N('lib');
47
-			self::error([ 'data' => [ 'message' => $l->t('Application is not enabled'), 'error' => 'application_not_enabled' ]]);
48
-			exit();
49
-		}
50
-	}
38
+    /**
39
+     * Check if the app is enabled, send json error msg if not
40
+     * @param string $app
41
+     * @deprecated Use the AppFramework instead. It will automatically check if the app is enabled.
42
+     * @suppress PhanDeprecatedFunction
43
+     */
44
+    public static function checkAppEnabled($app) {
45
+        if( !\OC::$server->getAppManager()->isEnabledForUser($app)) {
46
+            $l = \OC::$server->getL10N('lib');
47
+            self::error([ 'data' => [ 'message' => $l->t('Application is not enabled'), 'error' => 'application_not_enabled' ]]);
48
+            exit();
49
+        }
50
+    }
51 51
 
52
-	/**
53
-	 * Check if the user is logged in, send json error msg if not
54
-	 * @deprecated Use annotation based ACLs from the AppFramework instead
55
-	 * @suppress PhanDeprecatedFunction
56
-	 */
57
-	public static function checkLoggedIn() {
58
-		$twoFactorAuthManger = \OC::$server->getTwoFactorAuthManager();
59
-		if( !\OC::$server->getUserSession()->isLoggedIn()
60
-			|| $twoFactorAuthManger->needsSecondFactor(\OC::$server->getUserSession()->getUser())) {
61
-			$l = \OC::$server->getL10N('lib');
62
-			http_response_code(\OCP\AppFramework\Http::STATUS_UNAUTHORIZED);
63
-			self::error([ 'data' => [ 'message' => $l->t('Authentication error'), 'error' => 'authentication_error' ]]);
64
-			exit();
65
-		}
66
-	}
52
+    /**
53
+     * Check if the user is logged in, send json error msg if not
54
+     * @deprecated Use annotation based ACLs from the AppFramework instead
55
+     * @suppress PhanDeprecatedFunction
56
+     */
57
+    public static function checkLoggedIn() {
58
+        $twoFactorAuthManger = \OC::$server->getTwoFactorAuthManager();
59
+        if( !\OC::$server->getUserSession()->isLoggedIn()
60
+            || $twoFactorAuthManger->needsSecondFactor(\OC::$server->getUserSession()->getUser())) {
61
+            $l = \OC::$server->getL10N('lib');
62
+            http_response_code(\OCP\AppFramework\Http::STATUS_UNAUTHORIZED);
63
+            self::error([ 'data' => [ 'message' => $l->t('Authentication error'), 'error' => 'authentication_error' ]]);
64
+            exit();
65
+        }
66
+    }
67 67
 
68
-	/**
69
-	 * Check an ajax get/post call if the request token is valid, send json error msg if not.
70
-	 * @deprecated Use annotation based CSRF checks from the AppFramework instead
71
-	 * @suppress PhanDeprecatedFunction
72
-	 */
73
-	public static function callCheck() {
74
-		if(!\OC::$server->getRequest()->passesStrictCookieCheck()) {
75
-			header('Location: '.\OC::$WEBROOT);
76
-			exit();
77
-		}
68
+    /**
69
+     * Check an ajax get/post call if the request token is valid, send json error msg if not.
70
+     * @deprecated Use annotation based CSRF checks from the AppFramework instead
71
+     * @suppress PhanDeprecatedFunction
72
+     */
73
+    public static function callCheck() {
74
+        if(!\OC::$server->getRequest()->passesStrictCookieCheck()) {
75
+            header('Location: '.\OC::$WEBROOT);
76
+            exit();
77
+        }
78 78
 
79
-		if( !\OC::$server->getRequest()->passesCSRFCheck()) {
80
-			$l = \OC::$server->getL10N('lib');
81
-			self::error([ 'data' => [ 'message' => $l->t('Token expired. Please reload page.'), 'error' => 'token_expired' ]]);
82
-			exit();
83
-		}
84
-	}
79
+        if( !\OC::$server->getRequest()->passesCSRFCheck()) {
80
+            $l = \OC::$server->getL10N('lib');
81
+            self::error([ 'data' => [ 'message' => $l->t('Token expired. Please reload page.'), 'error' => 'token_expired' ]]);
82
+            exit();
83
+        }
84
+    }
85 85
 
86
-	/**
87
-	 * Check if the user is a admin, send json error msg if not.
88
-	 * @deprecated Use annotation based ACLs from the AppFramework instead
89
-	 * @suppress PhanDeprecatedFunction
90
-	 */
91
-	public static function checkAdminUser() {
92
-		if( !OC_User::isAdminUser(OC_User::getUser())) {
93
-			$l = \OC::$server->getL10N('lib');
94
-			self::error([ 'data' => [ 'message' => $l->t('Authentication error'), 'error' => 'authentication_error' ]]);
95
-			exit();
96
-		}
97
-	}
86
+    /**
87
+     * Check if the user is a admin, send json error msg if not.
88
+     * @deprecated Use annotation based ACLs from the AppFramework instead
89
+     * @suppress PhanDeprecatedFunction
90
+     */
91
+    public static function checkAdminUser() {
92
+        if( !OC_User::isAdminUser(OC_User::getUser())) {
93
+            $l = \OC::$server->getL10N('lib');
94
+            self::error([ 'data' => [ 'message' => $l->t('Authentication error'), 'error' => 'authentication_error' ]]);
95
+            exit();
96
+        }
97
+    }
98 98
 
99
-	/**
100
-	 * Send json error msg
101
-	 * @deprecated Use a AppFramework JSONResponse instead
102
-	 * @suppress PhanDeprecatedFunction
103
-	 */
104
-	public static function error($data = []) {
105
-		$data['status'] = 'error';
106
-		header( 'Content-Type: application/json; charset=utf-8');
107
-		echo self::encode($data);
108
-	}
99
+    /**
100
+     * Send json error msg
101
+     * @deprecated Use a AppFramework JSONResponse instead
102
+     * @suppress PhanDeprecatedFunction
103
+     */
104
+    public static function error($data = []) {
105
+        $data['status'] = 'error';
106
+        header( 'Content-Type: application/json; charset=utf-8');
107
+        echo self::encode($data);
108
+    }
109 109
 
110
-	/**
111
-	 * Send json success msg
112
-	 * @deprecated Use a AppFramework JSONResponse instead
113
-	 * @suppress PhanDeprecatedFunction
114
-	 */
115
-	public static function success($data = []) {
116
-		$data['status'] = 'success';
117
-		header( 'Content-Type: application/json; charset=utf-8');
118
-		echo self::encode($data);
119
-	}
110
+    /**
111
+     * Send json success msg
112
+     * @deprecated Use a AppFramework JSONResponse instead
113
+     * @suppress PhanDeprecatedFunction
114
+     */
115
+    public static function success($data = []) {
116
+        $data['status'] = 'success';
117
+        header( 'Content-Type: application/json; charset=utf-8');
118
+        echo self::encode($data);
119
+    }
120 120
 
121
-	/**
122
-	 * Convert OC_L10N_String to string, for use in json encodings
123
-	 */
124
-	protected static function to_string(&$value) {
125
-		if ($value instanceof \OC\L10N\L10NString) {
126
-			$value = (string)$value;
127
-		}
128
-	}
121
+    /**
122
+     * Convert OC_L10N_String to string, for use in json encodings
123
+     */
124
+    protected static function to_string(&$value) {
125
+        if ($value instanceof \OC\L10N\L10NString) {
126
+            $value = (string)$value;
127
+        }
128
+    }
129 129
 
130
-	/**
131
-	 * Encode JSON
132
-	 * @deprecated Use a AppFramework JSONResponse instead
133
-	 */
134
-	public static function encode($data) {
135
-		if (is_array($data)) {
136
-			array_walk_recursive($data, ['OC_JSON', 'to_string']);
137
-		}
138
-		return json_encode($data, JSON_HEX_TAG);
139
-	}
130
+    /**
131
+     * Encode JSON
132
+     * @deprecated Use a AppFramework JSONResponse instead
133
+     */
134
+    public static function encode($data) {
135
+        if (is_array($data)) {
136
+            array_walk_recursive($data, ['OC_JSON', 'to_string']);
137
+        }
138
+        return json_encode($data, JSON_HEX_TAG);
139
+    }
140 140
 }
Please login to merge, or discard this patch.