Completed
Pull Request — master (#7531)
by Morris
19:33 queued 03:26
created
settings/ajax/uninstallapp.php 2 patches
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -27,14 +27,14 @@  discard block
 block discarded – undo
27 27
 
28 28
 $lastConfirm = (int) \OC::$server->getSession()->get('last-password-confirm');
29 29
 if ($lastConfirm < (time() - 30 * 60 + 15)) { // allow 15 seconds delay
30
-	$l = \OC::$server->getL10N('core');
31
-	OC_JSON::error(array( 'data' => array( 'message' => $l->t('Password confirmation is required'))));
32
-	exit();
30
+    $l = \OC::$server->getL10N('core');
31
+    OC_JSON::error(array( 'data' => array( 'message' => $l->t('Password confirmation is required'))));
32
+    exit();
33 33
 }
34 34
 
35 35
 if (!array_key_exists('appid', $_POST)) {
36
-	OC_JSON::error();
37
-	exit;
36
+    OC_JSON::error();
37
+    exit;
38 38
 }
39 39
 
40 40
 $appId = (string)$_POST['appid'];
@@ -42,11 +42,11 @@  discard block
 block discarded – undo
42 42
 
43 43
 $result = OC_App::removeApp($appId);
44 44
 if($result !== false) {
45
-	// FIXME: Clear the cache - move that into some sane helper method
46
-	\OC::$server->getMemCacheFactory()->createDistributed('settings')->remove('listApps-0');
47
-	\OC::$server->getMemCacheFactory()->createDistributed('settings')->remove('listApps-1');
48
-	OC_JSON::success(array('data' => array('appid' => $appId)));
45
+    // FIXME: Clear the cache - move that into some sane helper method
46
+    \OC::$server->getMemCacheFactory()->createDistributed('settings')->remove('listApps-0');
47
+    \OC::$server->getMemCacheFactory()->createDistributed('settings')->remove('listApps-1');
48
+    OC_JSON::success(array('data' => array('appid' => $appId)));
49 49
 } else {
50
-	$l = \OC::$server->getL10N('settings');
51
-	OC_JSON::error(array('data' => array( 'message' => $l->t("Couldn't remove app.") )));
50
+    $l = \OC::$server->getL10N('settings');
51
+    OC_JSON::error(array('data' => array( 'message' => $l->t("Couldn't remove app.") )));
52 52
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -28,7 +28,7 @@  discard block
 block discarded – undo
28 28
 $lastConfirm = (int) \OC::$server->getSession()->get('last-password-confirm');
29 29
 if ($lastConfirm < (time() - 30 * 60 + 15)) { // allow 15 seconds delay
30 30
 	$l = \OC::$server->getL10N('core');
31
-	OC_JSON::error(array( 'data' => array( 'message' => $l->t('Password confirmation is required'))));
31
+	OC_JSON::error(array('data' => array('message' => $l->t('Password confirmation is required'))));
32 32
 	exit();
33 33
 }
34 34
 
@@ -37,16 +37,16 @@  discard block
 block discarded – undo
37 37
 	exit;
38 38
 }
39 39
 
40
-$appId = (string)$_POST['appid'];
40
+$appId = (string) $_POST['appid'];
41 41
 $appId = OC_App::cleanAppId($appId);
42 42
 
43 43
 $result = OC_App::removeApp($appId);
44
-if($result !== false) {
44
+if ($result !== false) {
45 45
 	// FIXME: Clear the cache - move that into some sane helper method
46 46
 	\OC::$server->getMemCacheFactory()->createDistributed('settings')->remove('listApps-0');
47 47
 	\OC::$server->getMemCacheFactory()->createDistributed('settings')->remove('listApps-1');
48 48
 	OC_JSON::success(array('data' => array('appid' => $appId)));
49 49
 } else {
50 50
 	$l = \OC::$server->getL10N('settings');
51
-	OC_JSON::error(array('data' => array( 'message' => $l->t("Couldn't remove app.") )));
51
+	OC_JSON::error(array('data' => array('message' => $l->t("Couldn't remove app."))));
52 52
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/External/Storage.php 2 patches
Indentation   +323 added lines, -323 removed lines patch added patch discarded remove patch
@@ -42,328 +42,328 @@
 block discarded – undo
42 42
 use OCP\Files\StorageNotAvailableException;
43 43
 
44 44
 class Storage extends DAV implements ISharedStorage {
45
-	/** @var ICloudId */
46
-	private $cloudId;
47
-	/** @var string */
48
-	private $mountPoint;
49
-	/** @var string */
50
-	private $token;
51
-	/** @var \OCP\ICacheFactory */
52
-	private $memcacheFactory;
53
-	/** @var \OCP\Http\Client\IClientService */
54
-	private $httpClient;
55
-	/** @var bool */
56
-	private $updateChecked = false;
57
-
58
-	/**
59
-	 * @var \OCA\Files_Sharing\External\Manager
60
-	 */
61
-	private $manager;
62
-
63
-	public function __construct($options) {
64
-		$this->memcacheFactory = \OC::$server->getMemCacheFactory();
65
-		$this->httpClient = $options['HttpClientService'];
66
-
67
-		$this->manager = $options['manager'];
68
-		$this->cloudId = $options['cloudId'];
69
-		$discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
70
-
71
-		list($protocol, $remote) = explode('://', $this->cloudId->getRemote());
72
-		if (strpos($remote, '/')) {
73
-			list($host, $root) = explode('/', $remote, 2);
74
-		} else {
75
-			$host = $remote;
76
-			$root = '';
77
-		}
78
-		$secure = $protocol === 'https';
79
-		$federatedSharingEndpoints = $discoveryService->discover($this->cloudId->getRemote(), 'FEDERATED_SHARING');
80
-		$webDavEndpoint = isset($federatedSharingEndpoints['webdav']) ? $federatedSharingEndpoints['webdav'] : '/public.php/webdav';
81
-		$root = rtrim($root, '/') . $webDavEndpoint;
82
-		$this->mountPoint = $options['mountpoint'];
83
-		$this->token = $options['token'];
84
-
85
-		parent::__construct(array(
86
-			'secure' => $secure,
87
-			'host' => $host,
88
-			'root' => $root,
89
-			'user' => $options['token'],
90
-			'password' => (string)$options['password']
91
-		));
92
-	}
93
-
94
-	public function getWatcher($path = '', $storage = null) {
95
-		if (!$storage) {
96
-			$storage = $this;
97
-		}
98
-		if (!isset($this->watcher)) {
99
-			$this->watcher = new Watcher($storage);
100
-			$this->watcher->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE);
101
-		}
102
-		return $this->watcher;
103
-	}
104
-
105
-	public function getRemoteUser() {
106
-		return $this->cloudId->getUser();
107
-	}
108
-
109
-	public function getRemote() {
110
-		return $this->cloudId->getRemote();
111
-	}
112
-
113
-	public function getMountPoint() {
114
-		return $this->mountPoint;
115
-	}
116
-
117
-	public function getToken() {
118
-		return $this->token;
119
-	}
120
-
121
-	public function getPassword() {
122
-		return $this->password;
123
-	}
124
-
125
-	/**
126
-	 * @brief get id of the mount point
127
-	 * @return string
128
-	 */
129
-	public function getId() {
130
-		return 'shared::' . md5($this->token . '@' . $this->getRemote());
131
-	}
132
-
133
-	public function getCache($path = '', $storage = null) {
134
-		if (is_null($this->cache)) {
135
-			$this->cache = new Cache($this, $this->cloudId);
136
-		}
137
-		return $this->cache;
138
-	}
139
-
140
-	/**
141
-	 * @param string $path
142
-	 * @param \OC\Files\Storage\Storage $storage
143
-	 * @return \OCA\Files_Sharing\External\Scanner
144
-	 */
145
-	public function getScanner($path = '', $storage = null) {
146
-		if (!$storage) {
147
-			$storage = $this;
148
-		}
149
-		if (!isset($this->scanner)) {
150
-			$this->scanner = new Scanner($storage);
151
-		}
152
-		return $this->scanner;
153
-	}
154
-
155
-	/**
156
-	 * check if a file or folder has been updated since $time
157
-	 *
158
-	 * @param string $path
159
-	 * @param int $time
160
-	 * @throws \OCP\Files\StorageNotAvailableException
161
-	 * @throws \OCP\Files\StorageInvalidException
162
-	 * @return bool
163
-	 */
164
-	public function hasUpdated($path, $time) {
165
-		// since for owncloud webdav servers we can rely on etag propagation we only need to check the root of the storage
166
-		// because of that we only do one check for the entire storage per request
167
-		if ($this->updateChecked) {
168
-			return false;
169
-		}
170
-		$this->updateChecked = true;
171
-		try {
172
-			return parent::hasUpdated('', $time);
173
-		} catch (StorageInvalidException $e) {
174
-			// check if it needs to be removed
175
-			$this->checkStorageAvailability();
176
-			throw $e;
177
-		} catch (StorageNotAvailableException $e) {
178
-			// check if it needs to be removed or just temp unavailable
179
-			$this->checkStorageAvailability();
180
-			throw $e;
181
-		}
182
-	}
183
-
184
-	public function test() {
185
-		try {
186
-			return parent::test();
187
-		} catch (StorageInvalidException $e) {
188
-			// check if it needs to be removed
189
-			$this->checkStorageAvailability();
190
-			throw $e;
191
-		} catch (StorageNotAvailableException $e) {
192
-			// check if it needs to be removed or just temp unavailable
193
-			$this->checkStorageAvailability();
194
-			throw $e;
195
-		}
196
-	}
197
-
198
-	/**
199
-	 * Check whether this storage is permanently or temporarily
200
-	 * unavailable
201
-	 *
202
-	 * @throws \OCP\Files\StorageNotAvailableException
203
-	 * @throws \OCP\Files\StorageInvalidException
204
-	 */
205
-	public function checkStorageAvailability() {
206
-		// see if we can find out why the share is unavailable
207
-		try {
208
-			$this->getShareInfo();
209
-		} catch (NotFoundException $e) {
210
-			// a 404 can either mean that the share no longer exists or there is no Nextcloud on the remote
211
-			if ($this->testRemote()) {
212
-				// valid Nextcloud instance means that the public share no longer exists
213
-				// since this is permanent (re-sharing the file will create a new token)
214
-				// we remove the invalid storage
215
-				$this->manager->removeShare($this->mountPoint);
216
-				$this->manager->getMountManager()->removeMount($this->mountPoint);
217
-				throw new StorageInvalidException();
218
-			} else {
219
-				// Nextcloud instance is gone, likely to be a temporary server configuration error
220
-				throw new StorageNotAvailableException();
221
-			}
222
-		} catch (ForbiddenException $e) {
223
-			// auth error, remove share for now (provide a dialog in the future)
224
-			$this->manager->removeShare($this->mountPoint);
225
-			$this->manager->getMountManager()->removeMount($this->mountPoint);
226
-			throw new StorageInvalidException();
227
-		} catch (\GuzzleHttp\Exception\ConnectException $e) {
228
-			throw new StorageNotAvailableException();
229
-		} catch (\GuzzleHttp\Exception\RequestException $e) {
230
-			throw new StorageNotAvailableException();
231
-		} catch (\Exception $e) {
232
-			throw $e;
233
-		}
234
-	}
235
-
236
-	public function file_exists($path) {
237
-		if ($path === '') {
238
-			return true;
239
-		} else {
240
-			return parent::file_exists($path);
241
-		}
242
-	}
243
-
244
-	/**
245
-	 * check if the configured remote is a valid federated share provider
246
-	 *
247
-	 * @return bool
248
-	 */
249
-	protected function testRemote() {
250
-		try {
251
-			return $this->testRemoteUrl($this->getRemote() . '/ocs-provider/index.php')
252
-				|| $this->testRemoteUrl($this->getRemote() . '/ocs-provider/')
253
-				|| $this->testRemoteUrl($this->getRemote() . '/status.php');
254
-		} catch (\Exception $e) {
255
-			return false;
256
-		}
257
-	}
258
-
259
-	/**
260
-	 * @param string $url
261
-	 * @return bool
262
-	 */
263
-	private function testRemoteUrl($url) {
264
-		$cache = $this->memcacheFactory->createDistributed('files_sharing_remote_url');
265
-		if($cache->hasKey($url)) {
266
-			return (bool)$cache->get($url);
267
-		}
268
-
269
-		$client = $this->httpClient->newClient();
270
-		try {
271
-			$result = $client->get($url, [
272
-				'timeout' => 10,
273
-				'connect_timeout' => 10,
274
-			])->getBody();
275
-			$data = json_decode($result);
276
-			$returnValue = (is_object($data) && !empty($data->version));
277
-		} catch (ConnectException $e) {
278
-			$returnValue = false;
279
-		} catch (ClientException $e) {
280
-			$returnValue = false;
281
-		}
282
-
283
-		$cache->set($url, $returnValue, 60*60*24);
284
-		return $returnValue;
285
-	}
286
-
287
-	/**
288
-	 * Whether the remote is an ownCloud/Nextcloud, used since some sharing features are not
289
-	 * standardized. Let's use this to detect whether to use it.
290
-	 *
291
-	 * @return bool
292
-	 */
293
-	public function remoteIsOwnCloud() {
294
-		if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) {
295
-			return false;
296
-		}
297
-		return true;
298
-	}
299
-
300
-	/**
301
-	 * @return mixed
302
-	 * @throws ForbiddenException
303
-	 * @throws NotFoundException
304
-	 * @throws \Exception
305
-	 */
306
-	public function getShareInfo() {
307
-		$remote = $this->getRemote();
308
-		$token = $this->getToken();
309
-		$password = $this->getPassword();
310
-
311
-		// If remote is not an ownCloud do not try to get any share info
312
-		if(!$this->remoteIsOwnCloud()) {
313
-			return ['status' => 'unsupported'];
314
-		}
315
-
316
-		$url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token;
317
-
318
-		// TODO: DI
319
-		$client = \OC::$server->getHTTPClientService()->newClient();
320
-		try {
321
-			$response = $client->post($url, [
322
-				'body' => ['password' => $password],
323
-				'timeout' => 10,
324
-				'connect_timeout' => 10,
325
-			]);
326
-		} catch (\GuzzleHttp\Exception\RequestException $e) {
327
-			if ($e->getCode() === Http::STATUS_UNAUTHORIZED || $e->getCode() === Http::STATUS_FORBIDDEN) {
328
-				throw new ForbiddenException();
329
-			}
330
-			if ($e->getCode() === Http::STATUS_NOT_FOUND) {
331
-				throw new NotFoundException();
332
-			}
333
-			// throw this to be on the safe side: the share will still be visible
334
-			// in the UI in case the failure is intermittent, and the user will
335
-			// be able to decide whether to remove it if it's really gone
336
-			throw new StorageNotAvailableException();
337
-		}
338
-
339
-		return json_decode($response->getBody(), true);
340
-	}
341
-
342
-	public function getOwner($path) {
343
-		return $this->cloudId->getDisplayId();
344
-	}
345
-
346
-	public function isSharable($path) {
347
-		if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
348
-			return false;
349
-		}
350
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_SHARE);
351
-	}
352
-
353
-	public function getPermissions($path) {
354
-		$response = $this->propfind($path);
355
-		if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) {
356
-			$permissions = $response['{http://open-collaboration-services.org/ns}share-permissions'];
357
-		} else {
358
-			// use default permission if remote server doesn't provide the share permissions
359
-			if ($this->is_dir($path)) {
360
-				$permissions = \OCP\Constants::PERMISSION_ALL;
361
-			} else {
362
-				$permissions = \OCP\Constants::PERMISSION_ALL & ~\OCP\Constants::PERMISSION_CREATE;
363
-			}
364
-		}
365
-
366
-		return $permissions;
367
-	}
45
+    /** @var ICloudId */
46
+    private $cloudId;
47
+    /** @var string */
48
+    private $mountPoint;
49
+    /** @var string */
50
+    private $token;
51
+    /** @var \OCP\ICacheFactory */
52
+    private $memcacheFactory;
53
+    /** @var \OCP\Http\Client\IClientService */
54
+    private $httpClient;
55
+    /** @var bool */
56
+    private $updateChecked = false;
57
+
58
+    /**
59
+     * @var \OCA\Files_Sharing\External\Manager
60
+     */
61
+    private $manager;
62
+
63
+    public function __construct($options) {
64
+        $this->memcacheFactory = \OC::$server->getMemCacheFactory();
65
+        $this->httpClient = $options['HttpClientService'];
66
+
67
+        $this->manager = $options['manager'];
68
+        $this->cloudId = $options['cloudId'];
69
+        $discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
70
+
71
+        list($protocol, $remote) = explode('://', $this->cloudId->getRemote());
72
+        if (strpos($remote, '/')) {
73
+            list($host, $root) = explode('/', $remote, 2);
74
+        } else {
75
+            $host = $remote;
76
+            $root = '';
77
+        }
78
+        $secure = $protocol === 'https';
79
+        $federatedSharingEndpoints = $discoveryService->discover($this->cloudId->getRemote(), 'FEDERATED_SHARING');
80
+        $webDavEndpoint = isset($federatedSharingEndpoints['webdav']) ? $federatedSharingEndpoints['webdav'] : '/public.php/webdav';
81
+        $root = rtrim($root, '/') . $webDavEndpoint;
82
+        $this->mountPoint = $options['mountpoint'];
83
+        $this->token = $options['token'];
84
+
85
+        parent::__construct(array(
86
+            'secure' => $secure,
87
+            'host' => $host,
88
+            'root' => $root,
89
+            'user' => $options['token'],
90
+            'password' => (string)$options['password']
91
+        ));
92
+    }
93
+
94
+    public function getWatcher($path = '', $storage = null) {
95
+        if (!$storage) {
96
+            $storage = $this;
97
+        }
98
+        if (!isset($this->watcher)) {
99
+            $this->watcher = new Watcher($storage);
100
+            $this->watcher->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE);
101
+        }
102
+        return $this->watcher;
103
+    }
104
+
105
+    public function getRemoteUser() {
106
+        return $this->cloudId->getUser();
107
+    }
108
+
109
+    public function getRemote() {
110
+        return $this->cloudId->getRemote();
111
+    }
112
+
113
+    public function getMountPoint() {
114
+        return $this->mountPoint;
115
+    }
116
+
117
+    public function getToken() {
118
+        return $this->token;
119
+    }
120
+
121
+    public function getPassword() {
122
+        return $this->password;
123
+    }
124
+
125
+    /**
126
+     * @brief get id of the mount point
127
+     * @return string
128
+     */
129
+    public function getId() {
130
+        return 'shared::' . md5($this->token . '@' . $this->getRemote());
131
+    }
132
+
133
+    public function getCache($path = '', $storage = null) {
134
+        if (is_null($this->cache)) {
135
+            $this->cache = new Cache($this, $this->cloudId);
136
+        }
137
+        return $this->cache;
138
+    }
139
+
140
+    /**
141
+     * @param string $path
142
+     * @param \OC\Files\Storage\Storage $storage
143
+     * @return \OCA\Files_Sharing\External\Scanner
144
+     */
145
+    public function getScanner($path = '', $storage = null) {
146
+        if (!$storage) {
147
+            $storage = $this;
148
+        }
149
+        if (!isset($this->scanner)) {
150
+            $this->scanner = new Scanner($storage);
151
+        }
152
+        return $this->scanner;
153
+    }
154
+
155
+    /**
156
+     * check if a file or folder has been updated since $time
157
+     *
158
+     * @param string $path
159
+     * @param int $time
160
+     * @throws \OCP\Files\StorageNotAvailableException
161
+     * @throws \OCP\Files\StorageInvalidException
162
+     * @return bool
163
+     */
164
+    public function hasUpdated($path, $time) {
165
+        // since for owncloud webdav servers we can rely on etag propagation we only need to check the root of the storage
166
+        // because of that we only do one check for the entire storage per request
167
+        if ($this->updateChecked) {
168
+            return false;
169
+        }
170
+        $this->updateChecked = true;
171
+        try {
172
+            return parent::hasUpdated('', $time);
173
+        } catch (StorageInvalidException $e) {
174
+            // check if it needs to be removed
175
+            $this->checkStorageAvailability();
176
+            throw $e;
177
+        } catch (StorageNotAvailableException $e) {
178
+            // check if it needs to be removed or just temp unavailable
179
+            $this->checkStorageAvailability();
180
+            throw $e;
181
+        }
182
+    }
183
+
184
+    public function test() {
185
+        try {
186
+            return parent::test();
187
+        } catch (StorageInvalidException $e) {
188
+            // check if it needs to be removed
189
+            $this->checkStorageAvailability();
190
+            throw $e;
191
+        } catch (StorageNotAvailableException $e) {
192
+            // check if it needs to be removed or just temp unavailable
193
+            $this->checkStorageAvailability();
194
+            throw $e;
195
+        }
196
+    }
197
+
198
+    /**
199
+     * Check whether this storage is permanently or temporarily
200
+     * unavailable
201
+     *
202
+     * @throws \OCP\Files\StorageNotAvailableException
203
+     * @throws \OCP\Files\StorageInvalidException
204
+     */
205
+    public function checkStorageAvailability() {
206
+        // see if we can find out why the share is unavailable
207
+        try {
208
+            $this->getShareInfo();
209
+        } catch (NotFoundException $e) {
210
+            // a 404 can either mean that the share no longer exists or there is no Nextcloud on the remote
211
+            if ($this->testRemote()) {
212
+                // valid Nextcloud instance means that the public share no longer exists
213
+                // since this is permanent (re-sharing the file will create a new token)
214
+                // we remove the invalid storage
215
+                $this->manager->removeShare($this->mountPoint);
216
+                $this->manager->getMountManager()->removeMount($this->mountPoint);
217
+                throw new StorageInvalidException();
218
+            } else {
219
+                // Nextcloud instance is gone, likely to be a temporary server configuration error
220
+                throw new StorageNotAvailableException();
221
+            }
222
+        } catch (ForbiddenException $e) {
223
+            // auth error, remove share for now (provide a dialog in the future)
224
+            $this->manager->removeShare($this->mountPoint);
225
+            $this->manager->getMountManager()->removeMount($this->mountPoint);
226
+            throw new StorageInvalidException();
227
+        } catch (\GuzzleHttp\Exception\ConnectException $e) {
228
+            throw new StorageNotAvailableException();
229
+        } catch (\GuzzleHttp\Exception\RequestException $e) {
230
+            throw new StorageNotAvailableException();
231
+        } catch (\Exception $e) {
232
+            throw $e;
233
+        }
234
+    }
235
+
236
+    public function file_exists($path) {
237
+        if ($path === '') {
238
+            return true;
239
+        } else {
240
+            return parent::file_exists($path);
241
+        }
242
+    }
243
+
244
+    /**
245
+     * check if the configured remote is a valid federated share provider
246
+     *
247
+     * @return bool
248
+     */
249
+    protected function testRemote() {
250
+        try {
251
+            return $this->testRemoteUrl($this->getRemote() . '/ocs-provider/index.php')
252
+                || $this->testRemoteUrl($this->getRemote() . '/ocs-provider/')
253
+                || $this->testRemoteUrl($this->getRemote() . '/status.php');
254
+        } catch (\Exception $e) {
255
+            return false;
256
+        }
257
+    }
258
+
259
+    /**
260
+     * @param string $url
261
+     * @return bool
262
+     */
263
+    private function testRemoteUrl($url) {
264
+        $cache = $this->memcacheFactory->createDistributed('files_sharing_remote_url');
265
+        if($cache->hasKey($url)) {
266
+            return (bool)$cache->get($url);
267
+        }
268
+
269
+        $client = $this->httpClient->newClient();
270
+        try {
271
+            $result = $client->get($url, [
272
+                'timeout' => 10,
273
+                'connect_timeout' => 10,
274
+            ])->getBody();
275
+            $data = json_decode($result);
276
+            $returnValue = (is_object($data) && !empty($data->version));
277
+        } catch (ConnectException $e) {
278
+            $returnValue = false;
279
+        } catch (ClientException $e) {
280
+            $returnValue = false;
281
+        }
282
+
283
+        $cache->set($url, $returnValue, 60*60*24);
284
+        return $returnValue;
285
+    }
286
+
287
+    /**
288
+     * Whether the remote is an ownCloud/Nextcloud, used since some sharing features are not
289
+     * standardized. Let's use this to detect whether to use it.
290
+     *
291
+     * @return bool
292
+     */
293
+    public function remoteIsOwnCloud() {
294
+        if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) {
295
+            return false;
296
+        }
297
+        return true;
298
+    }
299
+
300
+    /**
301
+     * @return mixed
302
+     * @throws ForbiddenException
303
+     * @throws NotFoundException
304
+     * @throws \Exception
305
+     */
306
+    public function getShareInfo() {
307
+        $remote = $this->getRemote();
308
+        $token = $this->getToken();
309
+        $password = $this->getPassword();
310
+
311
+        // If remote is not an ownCloud do not try to get any share info
312
+        if(!$this->remoteIsOwnCloud()) {
313
+            return ['status' => 'unsupported'];
314
+        }
315
+
316
+        $url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token;
317
+
318
+        // TODO: DI
319
+        $client = \OC::$server->getHTTPClientService()->newClient();
320
+        try {
321
+            $response = $client->post($url, [
322
+                'body' => ['password' => $password],
323
+                'timeout' => 10,
324
+                'connect_timeout' => 10,
325
+            ]);
326
+        } catch (\GuzzleHttp\Exception\RequestException $e) {
327
+            if ($e->getCode() === Http::STATUS_UNAUTHORIZED || $e->getCode() === Http::STATUS_FORBIDDEN) {
328
+                throw new ForbiddenException();
329
+            }
330
+            if ($e->getCode() === Http::STATUS_NOT_FOUND) {
331
+                throw new NotFoundException();
332
+            }
333
+            // throw this to be on the safe side: the share will still be visible
334
+            // in the UI in case the failure is intermittent, and the user will
335
+            // be able to decide whether to remove it if it's really gone
336
+            throw new StorageNotAvailableException();
337
+        }
338
+
339
+        return json_decode($response->getBody(), true);
340
+    }
341
+
342
+    public function getOwner($path) {
343
+        return $this->cloudId->getDisplayId();
344
+    }
345
+
346
+    public function isSharable($path) {
347
+        if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
348
+            return false;
349
+        }
350
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_SHARE);
351
+    }
352
+
353
+    public function getPermissions($path) {
354
+        $response = $this->propfind($path);
355
+        if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) {
356
+            $permissions = $response['{http://open-collaboration-services.org/ns}share-permissions'];
357
+        } else {
358
+            // use default permission if remote server doesn't provide the share permissions
359
+            if ($this->is_dir($path)) {
360
+                $permissions = \OCP\Constants::PERMISSION_ALL;
361
+            } else {
362
+                $permissions = \OCP\Constants::PERMISSION_ALL & ~\OCP\Constants::PERMISSION_CREATE;
363
+            }
364
+        }
365
+
366
+        return $permissions;
367
+    }
368 368
 
369 369
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -78,7 +78,7 @@  discard block
 block discarded – undo
78 78
 		$secure = $protocol === 'https';
79 79
 		$federatedSharingEndpoints = $discoveryService->discover($this->cloudId->getRemote(), 'FEDERATED_SHARING');
80 80
 		$webDavEndpoint = isset($federatedSharingEndpoints['webdav']) ? $federatedSharingEndpoints['webdav'] : '/public.php/webdav';
81
-		$root = rtrim($root, '/') . $webDavEndpoint;
81
+		$root = rtrim($root, '/').$webDavEndpoint;
82 82
 		$this->mountPoint = $options['mountpoint'];
83 83
 		$this->token = $options['token'];
84 84
 
@@ -87,7 +87,7 @@  discard block
 block discarded – undo
87 87
 			'host' => $host,
88 88
 			'root' => $root,
89 89
 			'user' => $options['token'],
90
-			'password' => (string)$options['password']
90
+			'password' => (string) $options['password']
91 91
 		));
92 92
 	}
93 93
 
@@ -127,7 +127,7 @@  discard block
 block discarded – undo
127 127
 	 * @return string
128 128
 	 */
129 129
 	public function getId() {
130
-		return 'shared::' . md5($this->token . '@' . $this->getRemote());
130
+		return 'shared::'.md5($this->token.'@'.$this->getRemote());
131 131
 	}
132 132
 
133 133
 	public function getCache($path = '', $storage = null) {
@@ -248,9 +248,9 @@  discard block
 block discarded – undo
248 248
 	 */
249 249
 	protected function testRemote() {
250 250
 		try {
251
-			return $this->testRemoteUrl($this->getRemote() . '/ocs-provider/index.php')
252
-				|| $this->testRemoteUrl($this->getRemote() . '/ocs-provider/')
253
-				|| $this->testRemoteUrl($this->getRemote() . '/status.php');
251
+			return $this->testRemoteUrl($this->getRemote().'/ocs-provider/index.php')
252
+				|| $this->testRemoteUrl($this->getRemote().'/ocs-provider/')
253
+				|| $this->testRemoteUrl($this->getRemote().'/status.php');
254 254
 		} catch (\Exception $e) {
255 255
 			return false;
256 256
 		}
@@ -262,8 +262,8 @@  discard block
 block discarded – undo
262 262
 	 */
263 263
 	private function testRemoteUrl($url) {
264 264
 		$cache = $this->memcacheFactory->createDistributed('files_sharing_remote_url');
265
-		if($cache->hasKey($url)) {
266
-			return (bool)$cache->get($url);
265
+		if ($cache->hasKey($url)) {
266
+			return (bool) $cache->get($url);
267 267
 		}
268 268
 
269 269
 		$client = $this->httpClient->newClient();
@@ -280,7 +280,7 @@  discard block
 block discarded – undo
280 280
 			$returnValue = false;
281 281
 		}
282 282
 
283
-		$cache->set($url, $returnValue, 60*60*24);
283
+		$cache->set($url, $returnValue, 60 * 60 * 24);
284 284
 		return $returnValue;
285 285
 	}
286 286
 
@@ -291,7 +291,7 @@  discard block
 block discarded – undo
291 291
 	 * @return bool
292 292
 	 */
293 293
 	public function remoteIsOwnCloud() {
294
-		if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) {
294
+		if (defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote().'/status.php')) {
295 295
 			return false;
296 296
 		}
297 297
 		return true;
@@ -309,11 +309,11 @@  discard block
 block discarded – undo
309 309
 		$password = $this->getPassword();
310 310
 
311 311
 		// If remote is not an ownCloud do not try to get any share info
312
-		if(!$this->remoteIsOwnCloud()) {
312
+		if (!$this->remoteIsOwnCloud()) {
313 313
 			return ['status' => 'unsupported'];
314 314
 		}
315 315
 
316
-		$url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token;
316
+		$url = rtrim($remote, '/').'/index.php/apps/files_sharing/shareinfo?t='.$token;
317 317
 
318 318
 		// TODO: DI
319 319
 		$client = \OC::$server->getHTTPClientService()->newClient();
Please login to merge, or discard this patch.
apps/theming/lib/ThemingDefaults.php 2 patches
Indentation   +338 added lines, -338 removed lines patch added patch discarded remove patch
@@ -44,342 +44,342 @@
 block discarded – undo
44 44
 
45 45
 class ThemingDefaults extends \OC_Defaults {
46 46
 
47
-	/** @var IConfig */
48
-	private $config;
49
-	/** @var IL10N */
50
-	private $l;
51
-	/** @var IURLGenerator */
52
-	private $urlGenerator;
53
-	/** @var IAppData */
54
-	private $appData;
55
-	/** @var ICacheFactory */
56
-	private $cacheFactory;
57
-	/** @var Util */
58
-	private $util;
59
-	/** @var IAppManager */
60
-	private $appManager;
61
-	/** @var string */
62
-	private $name;
63
-	/** @var string */
64
-	private $title;
65
-	/** @var string */
66
-	private $entity;
67
-	/** @var string */
68
-	private $url;
69
-	/** @var string */
70
-	private $slogan;
71
-	/** @var string */
72
-	private $color;
73
-
74
-	/** @var string */
75
-	private $iTunesAppId;
76
-	/** @var string */
77
-	private $iOSClientUrl;
78
-	/** @var string */
79
-	private $AndroidClientUrl;
80
-
81
-	/**
82
-	 * ThemingDefaults constructor.
83
-	 *
84
-	 * @param IConfig $config
85
-	 * @param IL10N $l
86
-	 * @param IURLGenerator $urlGenerator
87
-	 * @param \OC_Defaults $defaults
88
-	 * @param IAppData $appData
89
-	 * @param ICacheFactory $cacheFactory
90
-	 * @param Util $util
91
-	 * @param IAppManager $appManager
92
-	 */
93
-	public function __construct(IConfig $config,
94
-								IL10N $l,
95
-								IURLGenerator $urlGenerator,
96
-								IAppData $appData,
97
-								ICacheFactory $cacheFactory,
98
-								Util $util,
99
-								IAppManager $appManager
100
-	) {
101
-		parent::__construct();
102
-		$this->config = $config;
103
-		$this->l = $l;
104
-		$this->urlGenerator = $urlGenerator;
105
-		$this->appData = $appData;
106
-		$this->cacheFactory = $cacheFactory;
107
-		$this->util = $util;
108
-		$this->appManager = $appManager;
109
-
110
-		$this->name = parent::getName();
111
-		$this->title = parent::getTitle();
112
-		$this->entity = parent::getEntity();
113
-		$this->url = parent::getBaseUrl();
114
-		$this->slogan = parent::getSlogan();
115
-		$this->color = parent::getColorPrimary();
116
-		$this->iTunesAppId = parent::getiTunesAppId();
117
-		$this->iOSClientUrl = parent::getiOSClientUrl();
118
-		$this->AndroidClientUrl = parent::getAndroidClientUrl();
119
-	}
120
-
121
-	public function getName() {
122
-		return strip_tags($this->config->getAppValue('theming', 'name', $this->name));
123
-	}
124
-
125
-	public function getHTMLName() {
126
-		return $this->config->getAppValue('theming', 'name', $this->name);
127
-	}
128
-
129
-	public function getTitle() {
130
-		return strip_tags($this->config->getAppValue('theming', 'name', $this->title));
131
-	}
132
-
133
-	public function getEntity() {
134
-		return strip_tags($this->config->getAppValue('theming', 'name', $this->entity));
135
-	}
136
-
137
-	public function getBaseUrl() {
138
-		return $this->config->getAppValue('theming', 'url', $this->url);
139
-	}
140
-
141
-	public function getSlogan() {
142
-		return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', $this->slogan));
143
-	}
144
-
145
-	public function getShortFooter() {
146
-		$slogan = $this->getSlogan();
147
-		$footer = '<a href="'. $this->getBaseUrl() . '" target="_blank"' .
148
-			' rel="noreferrer noopener">' .$this->getEntity() . '</a>'.
149
-			($slogan !== '' ? ' – ' . $slogan : '');
150
-
151
-		return $footer;
152
-	}
153
-
154
-	/**
155
-	 * Color that is used for the header as well as for mail headers
156
-	 *
157
-	 * @return string
158
-	 */
159
-	public function getColorPrimary() {
160
-		return $this->config->getAppValue('theming', 'color', $this->color);
161
-	}
162
-
163
-	/**
164
-	 * Themed logo url
165
-	 *
166
-	 * @param bool $useSvg Whether to point to the SVG image or a fallback
167
-	 * @return string
168
-	 */
169
-	public function getLogo($useSvg = true) {
170
-		$logo = $this->config->getAppValue('theming', 'logoMime', false);
171
-
172
-		$logoExists = true;
173
-		try {
174
-			$this->appData->getFolder('images')->getFile('logo');
175
-		} catch (\Exception $e) {
176
-			$logoExists = false;
177
-		}
178
-
179
-		$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
180
-
181
-		if(!$logo || !$logoExists) {
182
-			if($useSvg) {
183
-				$logo = $this->urlGenerator->imagePath('core', 'logo.svg');
184
-			} else {
185
-				$logo = $this->urlGenerator->imagePath('core', 'logo.png');
186
-			}
187
-			return $logo . '?v=' . $cacheBusterCounter;
188
-		}
189
-
190
-		return $this->urlGenerator->linkToRoute('theming.Theming.getLogo') . '?v=' . $cacheBusterCounter;
191
-	}
192
-
193
-	/**
194
-	 * Themed background image url
195
-	 *
196
-	 * @return string
197
-	 */
198
-	public function getBackground() {
199
-		$backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime',false);
200
-
201
-		$backgroundExists = true;
202
-		try {
203
-			$this->appData->getFolder('images')->getFile('background');
204
-		} catch (\Exception $e) {
205
-			$backgroundExists = false;
206
-		}
207
-
208
-		$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
209
-
210
-		if(!$backgroundLogo || !$backgroundExists) {
211
-			return $this->urlGenerator->imagePath('core','background.png') . '?v=' . $cacheBusterCounter;
212
-		}
213
-
214
-		return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground') . '?v=' . $cacheBusterCounter;
215
-	}
216
-
217
-	/**
218
-	 * @return string
219
-	 */
220
-	public function getiTunesAppId() {
221
-		return $this->config->getAppValue('theming', 'iTunesAppId', $this->iTunesAppId);
222
-	}
223
-
224
-	/**
225
-	 * @return string
226
-	 */
227
-	public function getiOSClientUrl() {
228
-		return $this->config->getAppValue('theming', 'iOSClientUrl', $this->iOSClientUrl);
229
-	}
230
-
231
-	/**
232
-	 * @return string
233
-	 */
234
-	public function getAndroidClientUrl() {
235
-		return $this->config->getAppValue('theming', 'AndroidClientUrl', $this->AndroidClientUrl);
236
-	}
237
-
238
-
239
-	/**
240
-	 * @return array scss variables to overwrite
241
-	 */
242
-	public function getScssVariables() {
243
-		$cache = $this->cacheFactory->createDistributed('theming');
244
-		if ($value = $cache->get('getScssVariables')) {
245
-			return $value;
246
-		}
247
-
248
-		$variables = [
249
-			'theming-cachebuster' => "'" . $this->config->getAppValue('theming', 'cachebuster', '0') . "'",
250
-			'theming-logo-mime' => "'" . $this->config->getAppValue('theming', 'logoMime', '') . "'",
251
-			'theming-background-mime' => "'" . $this->config->getAppValue('theming', 'backgroundMime', '') . "'"
252
-		];
253
-
254
-		$variables['image-logo'] = "'".$this->urlGenerator->getAbsoluteURL($this->getLogo())."'";
255
-		$variables['image-login-background'] = "'".$this->urlGenerator->getAbsoluteURL($this->getBackground())."'";
256
-		$variables['image-login-plain'] = 'false';
257
-
258
-		if ($this->config->getAppValue('theming', 'color', null) !== null) {
259
-			$variables['color-primary'] = $this->getColorPrimary();
260
-			$variables['color-primary-text'] = $this->getTextColorPrimary();
261
-			$variables['color-primary-element'] = $this->util->elementColor($this->getColorPrimary());
262
-		}
263
-
264
-		if ($this->config->getAppValue('theming', 'backgroundMime', null) === 'backgroundColor') {
265
-			$variables['image-login-plain'] = 'true';
266
-		}
267
-		$cache->set('getScssVariables', $variables);
268
-		return $variables;
269
-	}
270
-
271
-	/**
272
-	 * Check if the image should be replaced by the theming app
273
-	 * and return the new image location then
274
-	 *
275
-	 * @param string $app name of the app
276
-	 * @param string $image filename of the image
277
-	 * @return bool|string false if image should not replaced, otherwise the location of the image
278
-	 */
279
-	public function replaceImagePath($app, $image) {
280
-		if($app==='') {
281
-			$app = 'core';
282
-		}
283
-		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
284
-
285
-		if ($image === 'favicon.ico' && $this->shouldReplaceIcons()) {
286
-			return $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]) . '?v=' . $cacheBusterValue;
287
-		}
288
-		if ($image === 'favicon-touch.png' && $this->shouldReplaceIcons()) {
289
-			return $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]) . '?v=' . $cacheBusterValue;
290
-		}
291
-		if ($image === 'manifest.json') {
292
-			try {
293
-				$appPath = $this->appManager->getAppPath($app);
294
-				if (file_exists($appPath . '/img/manifest.json')) {
295
-					return false;
296
-				}
297
-			} catch (AppPathNotFoundException $e) {}
298
-			return $this->urlGenerator->linkToRoute('theming.Theming.getManifest') . '?v=' . $cacheBusterValue;
299
-		}
300
-		return false;
301
-	}
302
-
303
-	/**
304
-	 * Check if Imagemagick is enabled and if SVG is supported
305
-	 * otherwise we can't render custom icons
306
-	 *
307
-	 * @return bool
308
-	 */
309
-	public function shouldReplaceIcons() {
310
-		$cache = $this->cacheFactory->createDistributed('theming');
311
-		if($value = $cache->get('shouldReplaceIcons')) {
312
-			return (bool)$value;
313
-		}
314
-		$value = false;
315
-		if(extension_loaded('imagick')) {
316
-			$checkImagick = new \Imagick();
317
-			if (count($checkImagick->queryFormats('SVG')) >= 1) {
318
-				$value = true;
319
-			}
320
-			$checkImagick->clear();
321
-		}
322
-		$cache->set('shouldReplaceIcons', $value);
323
-		return $value;
324
-	}
325
-
326
-	/**
327
-	 * Increases the cache buster key
328
-	 */
329
-	private function increaseCacheBuster() {
330
-		$cacheBusterKey = $this->config->getAppValue('theming', 'cachebuster', '0');
331
-		$this->config->setAppValue('theming', 'cachebuster', (int)$cacheBusterKey+1);
332
-		$this->cacheFactory->createDistributed('theming')->clear('getScssVariables');
333
-	}
334
-
335
-	/**
336
-	 * Update setting in the database
337
-	 *
338
-	 * @param string $setting
339
-	 * @param string $value
340
-	 */
341
-	public function set($setting, $value) {
342
-		$this->config->setAppValue('theming', $setting, $value);
343
-		$this->increaseCacheBuster();
344
-	}
345
-
346
-	/**
347
-	 * Revert settings to the default value
348
-	 *
349
-	 * @param string $setting setting which should be reverted
350
-	 * @return string default value
351
-	 */
352
-	public function undo($setting) {
353
-		$this->config->deleteAppValue('theming', $setting);
354
-		$this->increaseCacheBuster();
355
-
356
-		switch ($setting) {
357
-			case 'name':
358
-				$returnValue = $this->getEntity();
359
-				break;
360
-			case 'url':
361
-				$returnValue = $this->getBaseUrl();
362
-				break;
363
-			case 'slogan':
364
-				$returnValue = $this->getSlogan();
365
-				break;
366
-			case 'color':
367
-				$returnValue = $this->getColorPrimary();
368
-				break;
369
-			default:
370
-				$returnValue = '';
371
-				break;
372
-		}
373
-
374
-		return $returnValue;
375
-	}
376
-
377
-	/**
378
-	 * Color of text in the header and primary buttons
379
-	 *
380
-	 * @return string
381
-	 */
382
-	public function getTextColorPrimary() {
383
-		return $this->util->invertTextColor($this->getColorPrimary()) ? '#000000' : '#ffffff';
384
-	}
47
+    /** @var IConfig */
48
+    private $config;
49
+    /** @var IL10N */
50
+    private $l;
51
+    /** @var IURLGenerator */
52
+    private $urlGenerator;
53
+    /** @var IAppData */
54
+    private $appData;
55
+    /** @var ICacheFactory */
56
+    private $cacheFactory;
57
+    /** @var Util */
58
+    private $util;
59
+    /** @var IAppManager */
60
+    private $appManager;
61
+    /** @var string */
62
+    private $name;
63
+    /** @var string */
64
+    private $title;
65
+    /** @var string */
66
+    private $entity;
67
+    /** @var string */
68
+    private $url;
69
+    /** @var string */
70
+    private $slogan;
71
+    /** @var string */
72
+    private $color;
73
+
74
+    /** @var string */
75
+    private $iTunesAppId;
76
+    /** @var string */
77
+    private $iOSClientUrl;
78
+    /** @var string */
79
+    private $AndroidClientUrl;
80
+
81
+    /**
82
+     * ThemingDefaults constructor.
83
+     *
84
+     * @param IConfig $config
85
+     * @param IL10N $l
86
+     * @param IURLGenerator $urlGenerator
87
+     * @param \OC_Defaults $defaults
88
+     * @param IAppData $appData
89
+     * @param ICacheFactory $cacheFactory
90
+     * @param Util $util
91
+     * @param IAppManager $appManager
92
+     */
93
+    public function __construct(IConfig $config,
94
+                                IL10N $l,
95
+                                IURLGenerator $urlGenerator,
96
+                                IAppData $appData,
97
+                                ICacheFactory $cacheFactory,
98
+                                Util $util,
99
+                                IAppManager $appManager
100
+    ) {
101
+        parent::__construct();
102
+        $this->config = $config;
103
+        $this->l = $l;
104
+        $this->urlGenerator = $urlGenerator;
105
+        $this->appData = $appData;
106
+        $this->cacheFactory = $cacheFactory;
107
+        $this->util = $util;
108
+        $this->appManager = $appManager;
109
+
110
+        $this->name = parent::getName();
111
+        $this->title = parent::getTitle();
112
+        $this->entity = parent::getEntity();
113
+        $this->url = parent::getBaseUrl();
114
+        $this->slogan = parent::getSlogan();
115
+        $this->color = parent::getColorPrimary();
116
+        $this->iTunesAppId = parent::getiTunesAppId();
117
+        $this->iOSClientUrl = parent::getiOSClientUrl();
118
+        $this->AndroidClientUrl = parent::getAndroidClientUrl();
119
+    }
120
+
121
+    public function getName() {
122
+        return strip_tags($this->config->getAppValue('theming', 'name', $this->name));
123
+    }
124
+
125
+    public function getHTMLName() {
126
+        return $this->config->getAppValue('theming', 'name', $this->name);
127
+    }
128
+
129
+    public function getTitle() {
130
+        return strip_tags($this->config->getAppValue('theming', 'name', $this->title));
131
+    }
132
+
133
+    public function getEntity() {
134
+        return strip_tags($this->config->getAppValue('theming', 'name', $this->entity));
135
+    }
136
+
137
+    public function getBaseUrl() {
138
+        return $this->config->getAppValue('theming', 'url', $this->url);
139
+    }
140
+
141
+    public function getSlogan() {
142
+        return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', $this->slogan));
143
+    }
144
+
145
+    public function getShortFooter() {
146
+        $slogan = $this->getSlogan();
147
+        $footer = '<a href="'. $this->getBaseUrl() . '" target="_blank"' .
148
+            ' rel="noreferrer noopener">' .$this->getEntity() . '</a>'.
149
+            ($slogan !== '' ? ' – ' . $slogan : '');
150
+
151
+        return $footer;
152
+    }
153
+
154
+    /**
155
+     * Color that is used for the header as well as for mail headers
156
+     *
157
+     * @return string
158
+     */
159
+    public function getColorPrimary() {
160
+        return $this->config->getAppValue('theming', 'color', $this->color);
161
+    }
162
+
163
+    /**
164
+     * Themed logo url
165
+     *
166
+     * @param bool $useSvg Whether to point to the SVG image or a fallback
167
+     * @return string
168
+     */
169
+    public function getLogo($useSvg = true) {
170
+        $logo = $this->config->getAppValue('theming', 'logoMime', false);
171
+
172
+        $logoExists = true;
173
+        try {
174
+            $this->appData->getFolder('images')->getFile('logo');
175
+        } catch (\Exception $e) {
176
+            $logoExists = false;
177
+        }
178
+
179
+        $cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
180
+
181
+        if(!$logo || !$logoExists) {
182
+            if($useSvg) {
183
+                $logo = $this->urlGenerator->imagePath('core', 'logo.svg');
184
+            } else {
185
+                $logo = $this->urlGenerator->imagePath('core', 'logo.png');
186
+            }
187
+            return $logo . '?v=' . $cacheBusterCounter;
188
+        }
189
+
190
+        return $this->urlGenerator->linkToRoute('theming.Theming.getLogo') . '?v=' . $cacheBusterCounter;
191
+    }
192
+
193
+    /**
194
+     * Themed background image url
195
+     *
196
+     * @return string
197
+     */
198
+    public function getBackground() {
199
+        $backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime',false);
200
+
201
+        $backgroundExists = true;
202
+        try {
203
+            $this->appData->getFolder('images')->getFile('background');
204
+        } catch (\Exception $e) {
205
+            $backgroundExists = false;
206
+        }
207
+
208
+        $cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
209
+
210
+        if(!$backgroundLogo || !$backgroundExists) {
211
+            return $this->urlGenerator->imagePath('core','background.png') . '?v=' . $cacheBusterCounter;
212
+        }
213
+
214
+        return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground') . '?v=' . $cacheBusterCounter;
215
+    }
216
+
217
+    /**
218
+     * @return string
219
+     */
220
+    public function getiTunesAppId() {
221
+        return $this->config->getAppValue('theming', 'iTunesAppId', $this->iTunesAppId);
222
+    }
223
+
224
+    /**
225
+     * @return string
226
+     */
227
+    public function getiOSClientUrl() {
228
+        return $this->config->getAppValue('theming', 'iOSClientUrl', $this->iOSClientUrl);
229
+    }
230
+
231
+    /**
232
+     * @return string
233
+     */
234
+    public function getAndroidClientUrl() {
235
+        return $this->config->getAppValue('theming', 'AndroidClientUrl', $this->AndroidClientUrl);
236
+    }
237
+
238
+
239
+    /**
240
+     * @return array scss variables to overwrite
241
+     */
242
+    public function getScssVariables() {
243
+        $cache = $this->cacheFactory->createDistributed('theming');
244
+        if ($value = $cache->get('getScssVariables')) {
245
+            return $value;
246
+        }
247
+
248
+        $variables = [
249
+            'theming-cachebuster' => "'" . $this->config->getAppValue('theming', 'cachebuster', '0') . "'",
250
+            'theming-logo-mime' => "'" . $this->config->getAppValue('theming', 'logoMime', '') . "'",
251
+            'theming-background-mime' => "'" . $this->config->getAppValue('theming', 'backgroundMime', '') . "'"
252
+        ];
253
+
254
+        $variables['image-logo'] = "'".$this->urlGenerator->getAbsoluteURL($this->getLogo())."'";
255
+        $variables['image-login-background'] = "'".$this->urlGenerator->getAbsoluteURL($this->getBackground())."'";
256
+        $variables['image-login-plain'] = 'false';
257
+
258
+        if ($this->config->getAppValue('theming', 'color', null) !== null) {
259
+            $variables['color-primary'] = $this->getColorPrimary();
260
+            $variables['color-primary-text'] = $this->getTextColorPrimary();
261
+            $variables['color-primary-element'] = $this->util->elementColor($this->getColorPrimary());
262
+        }
263
+
264
+        if ($this->config->getAppValue('theming', 'backgroundMime', null) === 'backgroundColor') {
265
+            $variables['image-login-plain'] = 'true';
266
+        }
267
+        $cache->set('getScssVariables', $variables);
268
+        return $variables;
269
+    }
270
+
271
+    /**
272
+     * Check if the image should be replaced by the theming app
273
+     * and return the new image location then
274
+     *
275
+     * @param string $app name of the app
276
+     * @param string $image filename of the image
277
+     * @return bool|string false if image should not replaced, otherwise the location of the image
278
+     */
279
+    public function replaceImagePath($app, $image) {
280
+        if($app==='') {
281
+            $app = 'core';
282
+        }
283
+        $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
284
+
285
+        if ($image === 'favicon.ico' && $this->shouldReplaceIcons()) {
286
+            return $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]) . '?v=' . $cacheBusterValue;
287
+        }
288
+        if ($image === 'favicon-touch.png' && $this->shouldReplaceIcons()) {
289
+            return $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]) . '?v=' . $cacheBusterValue;
290
+        }
291
+        if ($image === 'manifest.json') {
292
+            try {
293
+                $appPath = $this->appManager->getAppPath($app);
294
+                if (file_exists($appPath . '/img/manifest.json')) {
295
+                    return false;
296
+                }
297
+            } catch (AppPathNotFoundException $e) {}
298
+            return $this->urlGenerator->linkToRoute('theming.Theming.getManifest') . '?v=' . $cacheBusterValue;
299
+        }
300
+        return false;
301
+    }
302
+
303
+    /**
304
+     * Check if Imagemagick is enabled and if SVG is supported
305
+     * otherwise we can't render custom icons
306
+     *
307
+     * @return bool
308
+     */
309
+    public function shouldReplaceIcons() {
310
+        $cache = $this->cacheFactory->createDistributed('theming');
311
+        if($value = $cache->get('shouldReplaceIcons')) {
312
+            return (bool)$value;
313
+        }
314
+        $value = false;
315
+        if(extension_loaded('imagick')) {
316
+            $checkImagick = new \Imagick();
317
+            if (count($checkImagick->queryFormats('SVG')) >= 1) {
318
+                $value = true;
319
+            }
320
+            $checkImagick->clear();
321
+        }
322
+        $cache->set('shouldReplaceIcons', $value);
323
+        return $value;
324
+    }
325
+
326
+    /**
327
+     * Increases the cache buster key
328
+     */
329
+    private function increaseCacheBuster() {
330
+        $cacheBusterKey = $this->config->getAppValue('theming', 'cachebuster', '0');
331
+        $this->config->setAppValue('theming', 'cachebuster', (int)$cacheBusterKey+1);
332
+        $this->cacheFactory->createDistributed('theming')->clear('getScssVariables');
333
+    }
334
+
335
+    /**
336
+     * Update setting in the database
337
+     *
338
+     * @param string $setting
339
+     * @param string $value
340
+     */
341
+    public function set($setting, $value) {
342
+        $this->config->setAppValue('theming', $setting, $value);
343
+        $this->increaseCacheBuster();
344
+    }
345
+
346
+    /**
347
+     * Revert settings to the default value
348
+     *
349
+     * @param string $setting setting which should be reverted
350
+     * @return string default value
351
+     */
352
+    public function undo($setting) {
353
+        $this->config->deleteAppValue('theming', $setting);
354
+        $this->increaseCacheBuster();
355
+
356
+        switch ($setting) {
357
+            case 'name':
358
+                $returnValue = $this->getEntity();
359
+                break;
360
+            case 'url':
361
+                $returnValue = $this->getBaseUrl();
362
+                break;
363
+            case 'slogan':
364
+                $returnValue = $this->getSlogan();
365
+                break;
366
+            case 'color':
367
+                $returnValue = $this->getColorPrimary();
368
+                break;
369
+            default:
370
+                $returnValue = '';
371
+                break;
372
+        }
373
+
374
+        return $returnValue;
375
+    }
376
+
377
+    /**
378
+     * Color of text in the header and primary buttons
379
+     *
380
+     * @return string
381
+     */
382
+    public function getTextColorPrimary() {
383
+        return $this->util->invertTextColor($this->getColorPrimary()) ? '#000000' : '#ffffff';
384
+    }
385 385
 }
Please login to merge, or discard this patch.
Spacing   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -144,9 +144,9 @@  discard block
 block discarded – undo
144 144
 
145 145
 	public function getShortFooter() {
146 146
 		$slogan = $this->getSlogan();
147
-		$footer = '<a href="'. $this->getBaseUrl() . '" target="_blank"' .
148
-			' rel="noreferrer noopener">' .$this->getEntity() . '</a>'.
149
-			($slogan !== '' ? ' – ' . $slogan : '');
147
+		$footer = '<a href="'.$this->getBaseUrl().'" target="_blank"'.
148
+			' rel="noreferrer noopener">'.$this->getEntity().'</a>'.
149
+			($slogan !== '' ? ' – '.$slogan : '');
150 150
 
151 151
 		return $footer;
152 152
 	}
@@ -178,16 +178,16 @@  discard block
 block discarded – undo
178 178
 
179 179
 		$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
180 180
 
181
-		if(!$logo || !$logoExists) {
182
-			if($useSvg) {
181
+		if (!$logo || !$logoExists) {
182
+			if ($useSvg) {
183 183
 				$logo = $this->urlGenerator->imagePath('core', 'logo.svg');
184 184
 			} else {
185 185
 				$logo = $this->urlGenerator->imagePath('core', 'logo.png');
186 186
 			}
187
-			return $logo . '?v=' . $cacheBusterCounter;
187
+			return $logo.'?v='.$cacheBusterCounter;
188 188
 		}
189 189
 
190
-		return $this->urlGenerator->linkToRoute('theming.Theming.getLogo') . '?v=' . $cacheBusterCounter;
190
+		return $this->urlGenerator->linkToRoute('theming.Theming.getLogo').'?v='.$cacheBusterCounter;
191 191
 	}
192 192
 
193 193
 	/**
@@ -196,7 +196,7 @@  discard block
 block discarded – undo
196 196
 	 * @return string
197 197
 	 */
198 198
 	public function getBackground() {
199
-		$backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime',false);
199
+		$backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime', false);
200 200
 
201 201
 		$backgroundExists = true;
202 202
 		try {
@@ -207,11 +207,11 @@  discard block
 block discarded – undo
207 207
 
208 208
 		$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
209 209
 
210
-		if(!$backgroundLogo || !$backgroundExists) {
211
-			return $this->urlGenerator->imagePath('core','background.png') . '?v=' . $cacheBusterCounter;
210
+		if (!$backgroundLogo || !$backgroundExists) {
211
+			return $this->urlGenerator->imagePath('core', 'background.png').'?v='.$cacheBusterCounter;
212 212
 		}
213 213
 
214
-		return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground') . '?v=' . $cacheBusterCounter;
214
+		return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground').'?v='.$cacheBusterCounter;
215 215
 	}
216 216
 
217 217
 	/**
@@ -246,9 +246,9 @@  discard block
 block discarded – undo
246 246
 		}
247 247
 
248 248
 		$variables = [
249
-			'theming-cachebuster' => "'" . $this->config->getAppValue('theming', 'cachebuster', '0') . "'",
250
-			'theming-logo-mime' => "'" . $this->config->getAppValue('theming', 'logoMime', '') . "'",
251
-			'theming-background-mime' => "'" . $this->config->getAppValue('theming', 'backgroundMime', '') . "'"
249
+			'theming-cachebuster' => "'".$this->config->getAppValue('theming', 'cachebuster', '0')."'",
250
+			'theming-logo-mime' => "'".$this->config->getAppValue('theming', 'logoMime', '')."'",
251
+			'theming-background-mime' => "'".$this->config->getAppValue('theming', 'backgroundMime', '')."'"
252 252
 		];
253 253
 
254 254
 		$variables['image-logo'] = "'".$this->urlGenerator->getAbsoluteURL($this->getLogo())."'";
@@ -277,25 +277,25 @@  discard block
 block discarded – undo
277 277
 	 * @return bool|string false if image should not replaced, otherwise the location of the image
278 278
 	 */
279 279
 	public function replaceImagePath($app, $image) {
280
-		if($app==='') {
280
+		if ($app === '') {
281 281
 			$app = 'core';
282 282
 		}
283 283
 		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
284 284
 
285 285
 		if ($image === 'favicon.ico' && $this->shouldReplaceIcons()) {
286
-			return $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]) . '?v=' . $cacheBusterValue;
286
+			return $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]).'?v='.$cacheBusterValue;
287 287
 		}
288 288
 		if ($image === 'favicon-touch.png' && $this->shouldReplaceIcons()) {
289
-			return $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]) . '?v=' . $cacheBusterValue;
289
+			return $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]).'?v='.$cacheBusterValue;
290 290
 		}
291 291
 		if ($image === 'manifest.json') {
292 292
 			try {
293 293
 				$appPath = $this->appManager->getAppPath($app);
294
-				if (file_exists($appPath . '/img/manifest.json')) {
294
+				if (file_exists($appPath.'/img/manifest.json')) {
295 295
 					return false;
296 296
 				}
297 297
 			} catch (AppPathNotFoundException $e) {}
298
-			return $this->urlGenerator->linkToRoute('theming.Theming.getManifest') . '?v=' . $cacheBusterValue;
298
+			return $this->urlGenerator->linkToRoute('theming.Theming.getManifest').'?v='.$cacheBusterValue;
299 299
 		}
300 300
 		return false;
301 301
 	}
@@ -308,11 +308,11 @@  discard block
 block discarded – undo
308 308
 	 */
309 309
 	public function shouldReplaceIcons() {
310 310
 		$cache = $this->cacheFactory->createDistributed('theming');
311
-		if($value = $cache->get('shouldReplaceIcons')) {
312
-			return (bool)$value;
311
+		if ($value = $cache->get('shouldReplaceIcons')) {
312
+			return (bool) $value;
313 313
 		}
314 314
 		$value = false;
315
-		if(extension_loaded('imagick')) {
315
+		if (extension_loaded('imagick')) {
316 316
 			$checkImagick = new \Imagick();
317 317
 			if (count($checkImagick->queryFormats('SVG')) >= 1) {
318 318
 				$value = true;
@@ -328,7 +328,7 @@  discard block
 block discarded – undo
328 328
 	 */
329 329
 	private function increaseCacheBuster() {
330 330
 		$cacheBusterKey = $this->config->getAppValue('theming', 'cachebuster', '0');
331
-		$this->config->setAppValue('theming', 'cachebuster', (int)$cacheBusterKey+1);
331
+		$this->config->setAppValue('theming', 'cachebuster', (int) $cacheBusterKey + 1);
332 332
 		$this->cacheFactory->createDistributed('theming')->clear('getScssVariables');
333 333
 	}
334 334
 
Please login to merge, or discard this patch.
apps/user_ldap/lib/Proxy.php 2 patches
Indentation   +166 added lines, -166 removed lines patch added patch discarded remove patch
@@ -37,170 +37,170 @@
 block discarded – undo
37 37
 use OCA\User_LDAP\User\Manager;
38 38
 
39 39
 abstract class Proxy {
40
-	static private $accesses = array();
41
-	private $ldap = null;
42
-
43
-	/** @var \OCP\ICache|null */
44
-	private $cache;
45
-
46
-	/**
47
-	 * @param ILDAPWrapper $ldap
48
-	 */
49
-	public function __construct(ILDAPWrapper $ldap) {
50
-		$this->ldap = $ldap;
51
-		$memcache = \OC::$server->getMemCacheFactory();
52
-		if($memcache->isAvailable()) {
53
-			$this->cache = $memcache->createDistributed();
54
-		}
55
-	}
56
-
57
-	/**
58
-	 * @param string $configPrefix
59
-	 */
60
-	private function addAccess($configPrefix) {
61
-		static $ocConfig;
62
-		static $fs;
63
-		static $log;
64
-		static $avatarM;
65
-		static $userMap;
66
-		static $groupMap;
67
-		static $db;
68
-		static $coreUserManager;
69
-		static $coreNotificationManager;
70
-		if($fs === null) {
71
-			$ocConfig = \OC::$server->getConfig();
72
-			$fs       = new FilesystemHelper();
73
-			$log      = new LogWrapper();
74
-			$avatarM  = \OC::$server->getAvatarManager();
75
-			$db       = \OC::$server->getDatabaseConnection();
76
-			$userMap  = new UserMapping($db);
77
-			$groupMap = new GroupMapping($db);
78
-			$coreUserManager = \OC::$server->getUserManager();
79
-			$coreNotificationManager = \OC::$server->getNotificationManager();
80
-		}
81
-		$userManager =
82
-			new Manager($ocConfig, $fs, $log, $avatarM, new \OCP\Image(), $db,
83
-				$coreUserManager, $coreNotificationManager);
84
-		$connector = new Connection($this->ldap, $configPrefix);
85
-		$access = new Access($connector, $this->ldap, $userManager, new Helper($ocConfig), $ocConfig);
86
-		$access->setUserMapper($userMap);
87
-		$access->setGroupMapper($groupMap);
88
-		self::$accesses[$configPrefix] = $access;
89
-	}
90
-
91
-	/**
92
-	 * @param string $configPrefix
93
-	 * @return mixed
94
-	 */
95
-	protected function getAccess($configPrefix) {
96
-		if(!isset(self::$accesses[$configPrefix])) {
97
-			$this->addAccess($configPrefix);
98
-		}
99
-		return self::$accesses[$configPrefix];
100
-	}
101
-
102
-	/**
103
-	 * @param string $uid
104
-	 * @return string
105
-	 */
106
-	protected function getUserCacheKey($uid) {
107
-		return 'user-'.$uid.'-lastSeenOn';
108
-	}
109
-
110
-	/**
111
-	 * @param string $gid
112
-	 * @return string
113
-	 */
114
-	protected function getGroupCacheKey($gid) {
115
-		return 'group-'.$gid.'-lastSeenOn';
116
-	}
117
-
118
-	/**
119
-	 * @param string $id
120
-	 * @param string $method
121
-	 * @param array $parameters
122
-	 * @param bool $passOnWhen
123
-	 * @return mixed
124
-	 */
125
-	abstract protected function callOnLastSeenOn($id, $method, $parameters, $passOnWhen);
126
-
127
-	/**
128
-	 * @param string $id
129
-	 * @param string $method
130
-	 * @param array $parameters
131
-	 * @return mixed
132
-	 */
133
-	abstract protected function walkBackends($id, $method, $parameters);
134
-
135
-	/**
136
-	 * @param string $id
137
-	 * @return Access
138
-	 */
139
-	abstract public function getLDAPAccess($id);
140
-
141
-	/**
142
-	 * Takes care of the request to the User backend
143
-	 * @param string $id
144
-	 * @param string $method string, the method of the user backend that shall be called
145
-	 * @param array $parameters an array of parameters to be passed
146
-	 * @param bool $passOnWhen
147
-	 * @return mixed, the result of the specified method
148
-	 */
149
-	protected function handleRequest($id, $method, $parameters, $passOnWhen = false) {
150
-		$result = $this->callOnLastSeenOn($id,  $method, $parameters, $passOnWhen);
151
-		if($result === $passOnWhen) {
152
-			$result = $this->walkBackends($id, $method, $parameters);
153
-		}
154
-		return $result;
155
-	}
156
-
157
-	/**
158
-	 * @param string|null $key
159
-	 * @return string
160
-	 */
161
-	private function getCacheKey($key) {
162
-		$prefix = 'LDAP-Proxy-';
163
-		if($key === null) {
164
-			return $prefix;
165
-		}
166
-		return $prefix.md5($key);
167
-	}
168
-
169
-	/**
170
-	 * @param string $key
171
-	 * @return mixed|null
172
-	 */
173
-	public function getFromCache($key) {
174
-		if($this->cache === null) {
175
-			return null;
176
-		}
177
-
178
-		$key = $this->getCacheKey($key);
179
-		$value = $this->cache->get($key);
180
-		if ($value === null) {
181
-			return null;
182
-		}
183
-
184
-		return json_decode(base64_decode($value));
185
-	}
186
-
187
-	/**
188
-	 * @param string $key
189
-	 * @param mixed $value
190
-	 */
191
-	public function writeToCache($key, $value) {
192
-		if($this->cache === null) {
193
-			return;
194
-		}
195
-		$key   = $this->getCacheKey($key);
196
-		$value = base64_encode(json_encode($value));
197
-		$this->cache->set($key, $value, 2592000);
198
-	}
199
-
200
-	public function clearCache() {
201
-		if($this->cache === null) {
202
-			return;
203
-		}
204
-		$this->cache->clear($this->getCacheKey(null));
205
-	}
40
+    static private $accesses = array();
41
+    private $ldap = null;
42
+
43
+    /** @var \OCP\ICache|null */
44
+    private $cache;
45
+
46
+    /**
47
+     * @param ILDAPWrapper $ldap
48
+     */
49
+    public function __construct(ILDAPWrapper $ldap) {
50
+        $this->ldap = $ldap;
51
+        $memcache = \OC::$server->getMemCacheFactory();
52
+        if($memcache->isAvailable()) {
53
+            $this->cache = $memcache->createDistributed();
54
+        }
55
+    }
56
+
57
+    /**
58
+     * @param string $configPrefix
59
+     */
60
+    private function addAccess($configPrefix) {
61
+        static $ocConfig;
62
+        static $fs;
63
+        static $log;
64
+        static $avatarM;
65
+        static $userMap;
66
+        static $groupMap;
67
+        static $db;
68
+        static $coreUserManager;
69
+        static $coreNotificationManager;
70
+        if($fs === null) {
71
+            $ocConfig = \OC::$server->getConfig();
72
+            $fs       = new FilesystemHelper();
73
+            $log      = new LogWrapper();
74
+            $avatarM  = \OC::$server->getAvatarManager();
75
+            $db       = \OC::$server->getDatabaseConnection();
76
+            $userMap  = new UserMapping($db);
77
+            $groupMap = new GroupMapping($db);
78
+            $coreUserManager = \OC::$server->getUserManager();
79
+            $coreNotificationManager = \OC::$server->getNotificationManager();
80
+        }
81
+        $userManager =
82
+            new Manager($ocConfig, $fs, $log, $avatarM, new \OCP\Image(), $db,
83
+                $coreUserManager, $coreNotificationManager);
84
+        $connector = new Connection($this->ldap, $configPrefix);
85
+        $access = new Access($connector, $this->ldap, $userManager, new Helper($ocConfig), $ocConfig);
86
+        $access->setUserMapper($userMap);
87
+        $access->setGroupMapper($groupMap);
88
+        self::$accesses[$configPrefix] = $access;
89
+    }
90
+
91
+    /**
92
+     * @param string $configPrefix
93
+     * @return mixed
94
+     */
95
+    protected function getAccess($configPrefix) {
96
+        if(!isset(self::$accesses[$configPrefix])) {
97
+            $this->addAccess($configPrefix);
98
+        }
99
+        return self::$accesses[$configPrefix];
100
+    }
101
+
102
+    /**
103
+     * @param string $uid
104
+     * @return string
105
+     */
106
+    protected function getUserCacheKey($uid) {
107
+        return 'user-'.$uid.'-lastSeenOn';
108
+    }
109
+
110
+    /**
111
+     * @param string $gid
112
+     * @return string
113
+     */
114
+    protected function getGroupCacheKey($gid) {
115
+        return 'group-'.$gid.'-lastSeenOn';
116
+    }
117
+
118
+    /**
119
+     * @param string $id
120
+     * @param string $method
121
+     * @param array $parameters
122
+     * @param bool $passOnWhen
123
+     * @return mixed
124
+     */
125
+    abstract protected function callOnLastSeenOn($id, $method, $parameters, $passOnWhen);
126
+
127
+    /**
128
+     * @param string $id
129
+     * @param string $method
130
+     * @param array $parameters
131
+     * @return mixed
132
+     */
133
+    abstract protected function walkBackends($id, $method, $parameters);
134
+
135
+    /**
136
+     * @param string $id
137
+     * @return Access
138
+     */
139
+    abstract public function getLDAPAccess($id);
140
+
141
+    /**
142
+     * Takes care of the request to the User backend
143
+     * @param string $id
144
+     * @param string $method string, the method of the user backend that shall be called
145
+     * @param array $parameters an array of parameters to be passed
146
+     * @param bool $passOnWhen
147
+     * @return mixed, the result of the specified method
148
+     */
149
+    protected function handleRequest($id, $method, $parameters, $passOnWhen = false) {
150
+        $result = $this->callOnLastSeenOn($id,  $method, $parameters, $passOnWhen);
151
+        if($result === $passOnWhen) {
152
+            $result = $this->walkBackends($id, $method, $parameters);
153
+        }
154
+        return $result;
155
+    }
156
+
157
+    /**
158
+     * @param string|null $key
159
+     * @return string
160
+     */
161
+    private function getCacheKey($key) {
162
+        $prefix = 'LDAP-Proxy-';
163
+        if($key === null) {
164
+            return $prefix;
165
+        }
166
+        return $prefix.md5($key);
167
+    }
168
+
169
+    /**
170
+     * @param string $key
171
+     * @return mixed|null
172
+     */
173
+    public function getFromCache($key) {
174
+        if($this->cache === null) {
175
+            return null;
176
+        }
177
+
178
+        $key = $this->getCacheKey($key);
179
+        $value = $this->cache->get($key);
180
+        if ($value === null) {
181
+            return null;
182
+        }
183
+
184
+        return json_decode(base64_decode($value));
185
+    }
186
+
187
+    /**
188
+     * @param string $key
189
+     * @param mixed $value
190
+     */
191
+    public function writeToCache($key, $value) {
192
+        if($this->cache === null) {
193
+            return;
194
+        }
195
+        $key   = $this->getCacheKey($key);
196
+        $value = base64_encode(json_encode($value));
197
+        $this->cache->set($key, $value, 2592000);
198
+    }
199
+
200
+    public function clearCache() {
201
+        if($this->cache === null) {
202
+            return;
203
+        }
204
+        $this->cache->clear($this->getCacheKey(null));
205
+    }
206 206
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -49,7 +49,7 @@  discard block
 block discarded – undo
49 49
 	public function __construct(ILDAPWrapper $ldap) {
50 50
 		$this->ldap = $ldap;
51 51
 		$memcache = \OC::$server->getMemCacheFactory();
52
-		if($memcache->isAvailable()) {
52
+		if ($memcache->isAvailable()) {
53 53
 			$this->cache = $memcache->createDistributed();
54 54
 		}
55 55
 	}
@@ -67,7 +67,7 @@  discard block
 block discarded – undo
67 67
 		static $db;
68 68
 		static $coreUserManager;
69 69
 		static $coreNotificationManager;
70
-		if($fs === null) {
70
+		if ($fs === null) {
71 71
 			$ocConfig = \OC::$server->getConfig();
72 72
 			$fs       = new FilesystemHelper();
73 73
 			$log      = new LogWrapper();
@@ -93,7 +93,7 @@  discard block
 block discarded – undo
93 93
 	 * @return mixed
94 94
 	 */
95 95
 	protected function getAccess($configPrefix) {
96
-		if(!isset(self::$accesses[$configPrefix])) {
96
+		if (!isset(self::$accesses[$configPrefix])) {
97 97
 			$this->addAccess($configPrefix);
98 98
 		}
99 99
 		return self::$accesses[$configPrefix];
@@ -147,8 +147,8 @@  discard block
 block discarded – undo
147 147
 	 * @return mixed, the result of the specified method
148 148
 	 */
149 149
 	protected function handleRequest($id, $method, $parameters, $passOnWhen = false) {
150
-		$result = $this->callOnLastSeenOn($id,  $method, $parameters, $passOnWhen);
151
-		if($result === $passOnWhen) {
150
+		$result = $this->callOnLastSeenOn($id, $method, $parameters, $passOnWhen);
151
+		if ($result === $passOnWhen) {
152 152
 			$result = $this->walkBackends($id, $method, $parameters);
153 153
 		}
154 154
 		return $result;
@@ -160,7 +160,7 @@  discard block
 block discarded – undo
160 160
 	 */
161 161
 	private function getCacheKey($key) {
162 162
 		$prefix = 'LDAP-Proxy-';
163
-		if($key === null) {
163
+		if ($key === null) {
164 164
 			return $prefix;
165 165
 		}
166 166
 		return $prefix.md5($key);
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
 	 * @return mixed|null
172 172
 	 */
173 173
 	public function getFromCache($key) {
174
-		if($this->cache === null) {
174
+		if ($this->cache === null) {
175 175
 			return null;
176 176
 		}
177 177
 
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
 	 * @param mixed $value
190 190
 	 */
191 191
 	public function writeToCache($key, $value) {
192
-		if($this->cache === null) {
192
+		if ($this->cache === null) {
193 193
 			return;
194 194
 		}
195 195
 		$key   = $this->getCacheKey($key);
@@ -198,7 +198,7 @@  discard block
 block discarded – undo
198 198
 	}
199 199
 
200 200
 	public function clearCache() {
201
-		if($this->cache === null) {
201
+		if ($this->cache === null) {
202 202
 			return;
203 203
 		}
204 204
 		$this->cache->clear($this->getCacheKey(null));
Please login to merge, or discard this patch.
lib/private/Files/ObjectStore/Swift.php 2 patches
Indentation   +244 added lines, -244 removed lines patch added patch discarded remove patch
@@ -39,249 +39,249 @@
 block discarded – undo
39 39
 
40 40
 class Swift implements IObjectStore {
41 41
 
42
-	/**
43
-	 * @var \OpenCloud\OpenStack
44
-	 */
45
-	private $client;
46
-
47
-	/**
48
-	 * @var array
49
-	 */
50
-	private $params;
51
-
52
-	/**
53
-	 * @var \OpenCloud\ObjectStore\Service
54
-	 */
55
-	private $objectStoreService;
56
-
57
-	/**
58
-	 * @var \OpenCloud\ObjectStore\Resource\Container
59
-	 */
60
-	private $container;
61
-
62
-	private $memcache;
63
-
64
-	public function __construct($params) {
65
-		if (isset($params['bucket'])) {
66
-			$params['container'] = $params['bucket'];
67
-		}
68
-		if (!isset($params['container'])) {
69
-			$params['container'] = 'owncloud';
70
-		}
71
-		if (!isset($params['autocreate'])) {
72
-			// should only be true for tests
73
-			$params['autocreate'] = false;
74
-		}
75
-
76
-		if (isset($params['apiKey'])) {
77
-			$this->client = new Rackspace($params['url'], $params);
78
-			$cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket'];
79
-		} else {
80
-			$this->client = new OpenStack($params['url'], $params);
81
-			$cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket'];
82
-		}
83
-
84
-		$cacheFactory = \OC::$server->getMemCacheFactory();
85
-		$this->memcache = $cacheFactory->createDistributed('swift::' . $cacheKey);
86
-
87
-		$this->params = $params;
88
-	}
89
-
90
-	protected function init() {
91
-		if ($this->container) {
92
-			return;
93
-		}
94
-
95
-		$this->importToken();
96
-
97
-		/** @var Token $token */
98
-		$token = $this->client->getTokenObject();
99
-
100
-		if (!$token || $token->hasExpired()) {
101
-			try {
102
-				$this->client->authenticate();
103
-				$this->exportToken();
104
-			} catch (ClientErrorResponseException $e) {
105
-				$statusCode = $e->getResponse()->getStatusCode();
106
-				if ($statusCode == 412) {
107
-					throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
108
-				} else if ($statusCode === 401) {
109
-					throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
110
-				} else {
111
-					throw new StorageAuthException('Unknown error', $e);
112
-				}
113
-			}
114
-		}
115
-
116
-
117
-		/** @var Catalog $catalog */
118
-		$catalog = $this->client->getCatalog();
119
-
120
-		if (isset($this->params['serviceName'])) {
121
-			$serviceName = $this->params['serviceName'];
122
-		} else {
123
-			$serviceName = Service::DEFAULT_NAME;
124
-		}
125
-
126
-		if (isset($this->params['urlType'])) {
127
-			$urlType = $this->params['urlType'];
128
-			if ($urlType !== 'internalURL' && $urlType !== 'publicURL') {
129
-				throw new StorageNotAvailableException('Invalid url type');
130
-			}
131
-		} else {
132
-			$urlType = Service::DEFAULT_URL_TYPE;
133
-		}
134
-
135
-		$catalogItem = $this->getCatalogForService($catalog, $serviceName);
136
-		if (!$catalogItem) {
137
-			$available = implode(', ', $this->getAvailableServiceNames($catalog));
138
-			throw new StorageNotAvailableException(
139
-				"Service $serviceName not found in service catalog, available services: $available"
140
-			);
141
-		} else if (isset($this->params['region'])) {
142
-			$this->validateRegion($catalogItem, $this->params['region']);
143
-		}
144
-
145
-		$this->objectStoreService = $this->client->objectStoreService($serviceName, $this->params['region'], $urlType);
146
-
147
-		try {
148
-			$this->container = $this->objectStoreService->getContainer($this->params['container']);
149
-		} catch (ClientErrorResponseException $ex) {
150
-			// if the container does not exist and autocreate is true try to create the container on the fly
151
-			if (isset($this->params['autocreate']) && $this->params['autocreate'] === true) {
152
-				$this->container = $this->objectStoreService->createContainer($this->params['container']);
153
-			} else {
154
-				throw $ex;
155
-			}
156
-		}
157
-	}
158
-
159
-	private function exportToken() {
160
-		$export = $this->client->exportCredentials();
161
-		$export['catalog'] = array_map(function (CatalogItem $item) {
162
-			return [
163
-				'name' => $item->getName(),
164
-				'endpoints' => $item->getEndpoints(),
165
-				'type' => $item->getType()
166
-			];
167
-		}, $export['catalog']->getItems());
168
-		$this->memcache->set('token', json_encode($export));
169
-	}
170
-
171
-	private function importToken() {
172
-		$cachedTokenString = $this->memcache->get('token');
173
-		if ($cachedTokenString) {
174
-			$cachedToken = json_decode($cachedTokenString, true);
175
-			$cachedToken['catalog'] = array_map(function (array $item) {
176
-				$itemClass = new \stdClass();
177
-				$itemClass->name = $item['name'];
178
-				$itemClass->endpoints = array_map(function (array $endpoint) {
179
-					return (object) $endpoint;
180
-				}, $item['endpoints']);
181
-				$itemClass->type = $item['type'];
182
-
183
-				return $itemClass;
184
-			}, $cachedToken['catalog']);
185
-			try {
186
-				$this->client->importCredentials($cachedToken);
187
-			} catch (\Exception $e) {
188
-				$this->client->setTokenObject(new Token());
189
-			}
190
-		}
191
-	}
192
-
193
-	/**
194
-	 * @param Catalog $catalog
195
-	 * @param $name
196
-	 * @return null|CatalogItem
197
-	 */
198
-	private function getCatalogForService(Catalog $catalog, $name) {
199
-		foreach ($catalog->getItems() as $item) {
200
-			/** @var CatalogItem $item */
201
-			if ($item->hasType(Service::DEFAULT_TYPE) && $item->hasName($name)) {
202
-				return $item;
203
-			}
204
-		}
205
-
206
-		return null;
207
-	}
208
-
209
-	private function validateRegion(CatalogItem $item, $region) {
210
-		$endPoints = $item->getEndpoints();
211
-		foreach ($endPoints as $endPoint) {
212
-			if ($endPoint->region === $region) {
213
-				return;
214
-			}
215
-		}
216
-
217
-		$availableRegions = implode(', ', array_map(function ($endpoint) {
218
-			return $endpoint->region;
219
-		}, $endPoints));
220
-
221
-		throw new StorageNotAvailableException("Invalid region '$region', available regions: $availableRegions");
222
-	}
223
-
224
-	private function getAvailableServiceNames(Catalog $catalog) {
225
-		return array_map(function (CatalogItem $item) {
226
-			return $item->getName();
227
-		}, array_filter($catalog->getItems(), function (CatalogItem $item) {
228
-			return $item->hasType(Service::DEFAULT_TYPE);
229
-		}));
230
-	}
231
-
232
-	/**
233
-	 * @return string the container name where objects are stored
234
-	 */
235
-	public function getStorageId() {
236
-		return $this->params['container'];
237
-	}
238
-
239
-	/**
240
-	 * @param string $urn the unified resource name used to identify the object
241
-	 * @param resource $stream stream with the data to write
242
-	 * @throws Exception from openstack lib when something goes wrong
243
-	 */
244
-	public function writeObject($urn, $stream) {
245
-		$this->init();
246
-		$this->container->uploadObject($urn, $stream);
247
-	}
248
-
249
-	/**
250
-	 * @param string $urn the unified resource name used to identify the object
251
-	 * @return resource stream with the read data
252
-	 * @throws Exception from openstack lib when something goes wrong
253
-	 */
254
-	public function readObject($urn) {
255
-		$this->init();
256
-		$object = $this->container->getObject($urn);
257
-
258
-		// we need to keep a reference to objectContent or
259
-		// the stream will be closed before we can do anything with it
260
-		/** @var $objectContent \Guzzle\Http\EntityBody * */
261
-		$objectContent = $object->getContent();
262
-		$objectContent->rewind();
263
-
264
-		$stream = $objectContent->getStream();
265
-		// save the object content in the context of the stream to prevent it being gc'd until the stream is closed
266
-		stream_context_set_option($stream, 'swift', 'content', $objectContent);
267
-
268
-		RetryWrapper::wrap($stream);
269
-	}
270
-
271
-	/**
272
-	 * @param string $urn Unified Resource Name
273
-	 * @return void
274
-	 * @throws Exception from openstack lib when something goes wrong
275
-	 */
276
-	public function deleteObject($urn) {
277
-		$this->init();
278
-		// see https://github.com/rackspace/php-opencloud/issues/243#issuecomment-30032242
279
-		$this->container->dataObject()->setName($urn)->delete();
280
-	}
281
-
282
-	public function deleteContainer($recursive = false) {
283
-		$this->init();
284
-		$this->container->delete($recursive);
285
-	}
42
+    /**
43
+     * @var \OpenCloud\OpenStack
44
+     */
45
+    private $client;
46
+
47
+    /**
48
+     * @var array
49
+     */
50
+    private $params;
51
+
52
+    /**
53
+     * @var \OpenCloud\ObjectStore\Service
54
+     */
55
+    private $objectStoreService;
56
+
57
+    /**
58
+     * @var \OpenCloud\ObjectStore\Resource\Container
59
+     */
60
+    private $container;
61
+
62
+    private $memcache;
63
+
64
+    public function __construct($params) {
65
+        if (isset($params['bucket'])) {
66
+            $params['container'] = $params['bucket'];
67
+        }
68
+        if (!isset($params['container'])) {
69
+            $params['container'] = 'owncloud';
70
+        }
71
+        if (!isset($params['autocreate'])) {
72
+            // should only be true for tests
73
+            $params['autocreate'] = false;
74
+        }
75
+
76
+        if (isset($params['apiKey'])) {
77
+            $this->client = new Rackspace($params['url'], $params);
78
+            $cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket'];
79
+        } else {
80
+            $this->client = new OpenStack($params['url'], $params);
81
+            $cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket'];
82
+        }
83
+
84
+        $cacheFactory = \OC::$server->getMemCacheFactory();
85
+        $this->memcache = $cacheFactory->createDistributed('swift::' . $cacheKey);
86
+
87
+        $this->params = $params;
88
+    }
89
+
90
+    protected function init() {
91
+        if ($this->container) {
92
+            return;
93
+        }
94
+
95
+        $this->importToken();
96
+
97
+        /** @var Token $token */
98
+        $token = $this->client->getTokenObject();
99
+
100
+        if (!$token || $token->hasExpired()) {
101
+            try {
102
+                $this->client->authenticate();
103
+                $this->exportToken();
104
+            } catch (ClientErrorResponseException $e) {
105
+                $statusCode = $e->getResponse()->getStatusCode();
106
+                if ($statusCode == 412) {
107
+                    throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
108
+                } else if ($statusCode === 401) {
109
+                    throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
110
+                } else {
111
+                    throw new StorageAuthException('Unknown error', $e);
112
+                }
113
+            }
114
+        }
115
+
116
+
117
+        /** @var Catalog $catalog */
118
+        $catalog = $this->client->getCatalog();
119
+
120
+        if (isset($this->params['serviceName'])) {
121
+            $serviceName = $this->params['serviceName'];
122
+        } else {
123
+            $serviceName = Service::DEFAULT_NAME;
124
+        }
125
+
126
+        if (isset($this->params['urlType'])) {
127
+            $urlType = $this->params['urlType'];
128
+            if ($urlType !== 'internalURL' && $urlType !== 'publicURL') {
129
+                throw new StorageNotAvailableException('Invalid url type');
130
+            }
131
+        } else {
132
+            $urlType = Service::DEFAULT_URL_TYPE;
133
+        }
134
+
135
+        $catalogItem = $this->getCatalogForService($catalog, $serviceName);
136
+        if (!$catalogItem) {
137
+            $available = implode(', ', $this->getAvailableServiceNames($catalog));
138
+            throw new StorageNotAvailableException(
139
+                "Service $serviceName not found in service catalog, available services: $available"
140
+            );
141
+        } else if (isset($this->params['region'])) {
142
+            $this->validateRegion($catalogItem, $this->params['region']);
143
+        }
144
+
145
+        $this->objectStoreService = $this->client->objectStoreService($serviceName, $this->params['region'], $urlType);
146
+
147
+        try {
148
+            $this->container = $this->objectStoreService->getContainer($this->params['container']);
149
+        } catch (ClientErrorResponseException $ex) {
150
+            // if the container does not exist and autocreate is true try to create the container on the fly
151
+            if (isset($this->params['autocreate']) && $this->params['autocreate'] === true) {
152
+                $this->container = $this->objectStoreService->createContainer($this->params['container']);
153
+            } else {
154
+                throw $ex;
155
+            }
156
+        }
157
+    }
158
+
159
+    private function exportToken() {
160
+        $export = $this->client->exportCredentials();
161
+        $export['catalog'] = array_map(function (CatalogItem $item) {
162
+            return [
163
+                'name' => $item->getName(),
164
+                'endpoints' => $item->getEndpoints(),
165
+                'type' => $item->getType()
166
+            ];
167
+        }, $export['catalog']->getItems());
168
+        $this->memcache->set('token', json_encode($export));
169
+    }
170
+
171
+    private function importToken() {
172
+        $cachedTokenString = $this->memcache->get('token');
173
+        if ($cachedTokenString) {
174
+            $cachedToken = json_decode($cachedTokenString, true);
175
+            $cachedToken['catalog'] = array_map(function (array $item) {
176
+                $itemClass = new \stdClass();
177
+                $itemClass->name = $item['name'];
178
+                $itemClass->endpoints = array_map(function (array $endpoint) {
179
+                    return (object) $endpoint;
180
+                }, $item['endpoints']);
181
+                $itemClass->type = $item['type'];
182
+
183
+                return $itemClass;
184
+            }, $cachedToken['catalog']);
185
+            try {
186
+                $this->client->importCredentials($cachedToken);
187
+            } catch (\Exception $e) {
188
+                $this->client->setTokenObject(new Token());
189
+            }
190
+        }
191
+    }
192
+
193
+    /**
194
+     * @param Catalog $catalog
195
+     * @param $name
196
+     * @return null|CatalogItem
197
+     */
198
+    private function getCatalogForService(Catalog $catalog, $name) {
199
+        foreach ($catalog->getItems() as $item) {
200
+            /** @var CatalogItem $item */
201
+            if ($item->hasType(Service::DEFAULT_TYPE) && $item->hasName($name)) {
202
+                return $item;
203
+            }
204
+        }
205
+
206
+        return null;
207
+    }
208
+
209
+    private function validateRegion(CatalogItem $item, $region) {
210
+        $endPoints = $item->getEndpoints();
211
+        foreach ($endPoints as $endPoint) {
212
+            if ($endPoint->region === $region) {
213
+                return;
214
+            }
215
+        }
216
+
217
+        $availableRegions = implode(', ', array_map(function ($endpoint) {
218
+            return $endpoint->region;
219
+        }, $endPoints));
220
+
221
+        throw new StorageNotAvailableException("Invalid region '$region', available regions: $availableRegions");
222
+    }
223
+
224
+    private function getAvailableServiceNames(Catalog $catalog) {
225
+        return array_map(function (CatalogItem $item) {
226
+            return $item->getName();
227
+        }, array_filter($catalog->getItems(), function (CatalogItem $item) {
228
+            return $item->hasType(Service::DEFAULT_TYPE);
229
+        }));
230
+    }
231
+
232
+    /**
233
+     * @return string the container name where objects are stored
234
+     */
235
+    public function getStorageId() {
236
+        return $this->params['container'];
237
+    }
238
+
239
+    /**
240
+     * @param string $urn the unified resource name used to identify the object
241
+     * @param resource $stream stream with the data to write
242
+     * @throws Exception from openstack lib when something goes wrong
243
+     */
244
+    public function writeObject($urn, $stream) {
245
+        $this->init();
246
+        $this->container->uploadObject($urn, $stream);
247
+    }
248
+
249
+    /**
250
+     * @param string $urn the unified resource name used to identify the object
251
+     * @return resource stream with the read data
252
+     * @throws Exception from openstack lib when something goes wrong
253
+     */
254
+    public function readObject($urn) {
255
+        $this->init();
256
+        $object = $this->container->getObject($urn);
257
+
258
+        // we need to keep a reference to objectContent or
259
+        // the stream will be closed before we can do anything with it
260
+        /** @var $objectContent \Guzzle\Http\EntityBody * */
261
+        $objectContent = $object->getContent();
262
+        $objectContent->rewind();
263
+
264
+        $stream = $objectContent->getStream();
265
+        // save the object content in the context of the stream to prevent it being gc'd until the stream is closed
266
+        stream_context_set_option($stream, 'swift', 'content', $objectContent);
267
+
268
+        RetryWrapper::wrap($stream);
269
+    }
270
+
271
+    /**
272
+     * @param string $urn Unified Resource Name
273
+     * @return void
274
+     * @throws Exception from openstack lib when something goes wrong
275
+     */
276
+    public function deleteObject($urn) {
277
+        $this->init();
278
+        // see https://github.com/rackspace/php-opencloud/issues/243#issuecomment-30032242
279
+        $this->container->dataObject()->setName($urn)->delete();
280
+    }
281
+
282
+    public function deleteContainer($recursive = false) {
283
+        $this->init();
284
+        $this->container->delete($recursive);
285
+    }
286 286
 
287 287
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -75,14 +75,14 @@  discard block
 block discarded – undo
75 75
 
76 76
 		if (isset($params['apiKey'])) {
77 77
 			$this->client = new Rackspace($params['url'], $params);
78
-			$cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket'];
78
+			$cacheKey = $params['username'].'@'.$params['url'].'/'.$params['bucket'];
79 79
 		} else {
80 80
 			$this->client = new OpenStack($params['url'], $params);
81
-			$cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket'];
81
+			$cacheKey = $params['username'].'@'.$params['url'].'/'.$params['bucket'];
82 82
 		}
83 83
 
84 84
 		$cacheFactory = \OC::$server->getMemCacheFactory();
85
-		$this->memcache = $cacheFactory->createDistributed('swift::' . $cacheKey);
85
+		$this->memcache = $cacheFactory->createDistributed('swift::'.$cacheKey);
86 86
 
87 87
 		$this->params = $params;
88 88
 	}
@@ -158,7 +158,7 @@  discard block
 block discarded – undo
158 158
 
159 159
 	private function exportToken() {
160 160
 		$export = $this->client->exportCredentials();
161
-		$export['catalog'] = array_map(function (CatalogItem $item) {
161
+		$export['catalog'] = array_map(function(CatalogItem $item) {
162 162
 			return [
163 163
 				'name' => $item->getName(),
164 164
 				'endpoints' => $item->getEndpoints(),
@@ -172,10 +172,10 @@  discard block
 block discarded – undo
172 172
 		$cachedTokenString = $this->memcache->get('token');
173 173
 		if ($cachedTokenString) {
174 174
 			$cachedToken = json_decode($cachedTokenString, true);
175
-			$cachedToken['catalog'] = array_map(function (array $item) {
175
+			$cachedToken['catalog'] = array_map(function(array $item) {
176 176
 				$itemClass = new \stdClass();
177 177
 				$itemClass->name = $item['name'];
178
-				$itemClass->endpoints = array_map(function (array $endpoint) {
178
+				$itemClass->endpoints = array_map(function(array $endpoint) {
179 179
 					return (object) $endpoint;
180 180
 				}, $item['endpoints']);
181 181
 				$itemClass->type = $item['type'];
@@ -214,7 +214,7 @@  discard block
 block discarded – undo
214 214
 			}
215 215
 		}
216 216
 
217
-		$availableRegions = implode(', ', array_map(function ($endpoint) {
217
+		$availableRegions = implode(', ', array_map(function($endpoint) {
218 218
 			return $endpoint->region;
219 219
 		}, $endPoints));
220 220
 
@@ -222,9 +222,9 @@  discard block
 block discarded – undo
222 222
 	}
223 223
 
224 224
 	private function getAvailableServiceNames(Catalog $catalog) {
225
-		return array_map(function (CatalogItem $item) {
225
+		return array_map(function(CatalogItem $item) {
226 226
 			return $item->getName();
227
-		}, array_filter($catalog->getItems(), function (CatalogItem $item) {
227
+		}, array_filter($catalog->getItems(), function(CatalogItem $item) {
228 228
 			return $item->hasType(Service::DEFAULT_TYPE);
229 229
 		}));
230 230
 	}
Please login to merge, or discard this patch.
lib/private/Security/RateLimiting/Backend/MemoryCache.php 1 patch
Indentation   +71 added lines, -71 removed lines patch added patch discarded remove patch
@@ -34,85 +34,85 @@
 block discarded – undo
34 34
  * @package OC\Security\RateLimiting\Backend
35 35
  */
36 36
 class MemoryCache implements IBackend {
37
-	/** @var ICache */
38
-	private $cache;
39
-	/** @var ITimeFactory */
40
-	private $timeFactory;
37
+    /** @var ICache */
38
+    private $cache;
39
+    /** @var ITimeFactory */
40
+    private $timeFactory;
41 41
 
42
-	/**
43
-	 * @param ICacheFactory $cacheFactory
44
-	 * @param ITimeFactory $timeFactory
45
-	 */
46
-	public function __construct(ICacheFactory $cacheFactory,
47
-								ITimeFactory $timeFactory) {
48
-		$this->cache = $cacheFactory->createDistributed(__CLASS__);
49
-		$this->timeFactory = $timeFactory;
50
-	}
42
+    /**
43
+     * @param ICacheFactory $cacheFactory
44
+     * @param ITimeFactory $timeFactory
45
+     */
46
+    public function __construct(ICacheFactory $cacheFactory,
47
+                                ITimeFactory $timeFactory) {
48
+        $this->cache = $cacheFactory->createDistributed(__CLASS__);
49
+        $this->timeFactory = $timeFactory;
50
+    }
51 51
 
52
-	/**
53
-	 * @param string $methodIdentifier
54
-	 * @param string $userIdentifier
55
-	 * @return string
56
-	 */
57
-	private function hash($methodIdentifier,
58
-						  $userIdentifier) {
59
-		return hash('sha512', $methodIdentifier . $userIdentifier);
60
-	}
52
+    /**
53
+     * @param string $methodIdentifier
54
+     * @param string $userIdentifier
55
+     * @return string
56
+     */
57
+    private function hash($methodIdentifier,
58
+                            $userIdentifier) {
59
+        return hash('sha512', $methodIdentifier . $userIdentifier);
60
+    }
61 61
 
62
-	/**
63
-	 * @param string $identifier
64
-	 * @return array
65
-	 */
66
-	private function getExistingAttempts($identifier) {
67
-		$cachedAttempts = json_decode($this->cache->get($identifier), true);
68
-		if(is_array($cachedAttempts)) {
69
-			return $cachedAttempts;
70
-		}
62
+    /**
63
+     * @param string $identifier
64
+     * @return array
65
+     */
66
+    private function getExistingAttempts($identifier) {
67
+        $cachedAttempts = json_decode($this->cache->get($identifier), true);
68
+        if(is_array($cachedAttempts)) {
69
+            return $cachedAttempts;
70
+        }
71 71
 
72
-		return [];
73
-	}
72
+        return [];
73
+    }
74 74
 
75
-	/**
76
-	 * {@inheritDoc}
77
-	 */
78
-	public function getAttempts($methodIdentifier,
79
-								$userIdentifier,
80
-								$seconds) {
81
-		$identifier = $this->hash($methodIdentifier, $userIdentifier);
82
-		$existingAttempts = $this->getExistingAttempts($identifier);
75
+    /**
76
+     * {@inheritDoc}
77
+     */
78
+    public function getAttempts($methodIdentifier,
79
+                                $userIdentifier,
80
+                                $seconds) {
81
+        $identifier = $this->hash($methodIdentifier, $userIdentifier);
82
+        $existingAttempts = $this->getExistingAttempts($identifier);
83 83
 
84
-		$count = 0;
85
-		$currentTime = $this->timeFactory->getTime();
86
-		/** @var array $existingAttempts */
87
-		foreach ($existingAttempts as $attempt) {
88
-			if(($attempt + $seconds) > $currentTime) {
89
-				$count++;
90
-			}
91
-		}
84
+        $count = 0;
85
+        $currentTime = $this->timeFactory->getTime();
86
+        /** @var array $existingAttempts */
87
+        foreach ($existingAttempts as $attempt) {
88
+            if(($attempt + $seconds) > $currentTime) {
89
+                $count++;
90
+            }
91
+        }
92 92
 
93
-		return $count;
94
-	}
93
+        return $count;
94
+    }
95 95
 
96
-	/**
97
-	 * {@inheritDoc}
98
-	 */
99
-	public function registerAttempt($methodIdentifier,
100
-									$userIdentifier,
101
-									$period) {
102
-		$identifier = $this->hash($methodIdentifier, $userIdentifier);
103
-		$existingAttempts = $this->getExistingAttempts($identifier);
104
-		$currentTime = $this->timeFactory->getTime();
96
+    /**
97
+     * {@inheritDoc}
98
+     */
99
+    public function registerAttempt($methodIdentifier,
100
+                                    $userIdentifier,
101
+                                    $period) {
102
+        $identifier = $this->hash($methodIdentifier, $userIdentifier);
103
+        $existingAttempts = $this->getExistingAttempts($identifier);
104
+        $currentTime = $this->timeFactory->getTime();
105 105
 
106
-		// Unset all attempts older than $period
107
-		foreach ($existingAttempts as $key => $attempt) {
108
-			if(($attempt + $period) < $currentTime) {
109
-				unset($existingAttempts[$key]);
110
-			}
111
-		}
112
-		$existingAttempts = array_values($existingAttempts);
106
+        // Unset all attempts older than $period
107
+        foreach ($existingAttempts as $key => $attempt) {
108
+            if(($attempt + $period) < $currentTime) {
109
+                unset($existingAttempts[$key]);
110
+            }
111
+        }
112
+        $existingAttempts = array_values($existingAttempts);
113 113
 
114
-		// Store the new attempt
115
-		$existingAttempts[] = (string)$currentTime;
116
-		$this->cache->set($identifier, json_encode($existingAttempts));
117
-	}
114
+        // Store the new attempt
115
+        $existingAttempts[] = (string)$currentTime;
116
+        $this->cache->set($identifier, json_encode($existingAttempts));
117
+    }
118 118
 }
Please login to merge, or discard this patch.
lib/private/OCS/DiscoveryService.php 1 patch
Indentation   +89 added lines, -89 removed lines patch added patch discarded remove patch
@@ -33,94 +33,94 @@
 block discarded – undo
33 33
 
34 34
 class DiscoveryService implements IDiscoveryService {
35 35
 
36
-	/** @var ICache */
37
-	private $cache;
38
-
39
-	/** @var IClient */
40
-	private $client;
41
-
42
-	/**
43
-	 * @param ICacheFactory $cacheFactory
44
-	 * @param IClientService $clientService
45
-	 */
46
-	public function __construct(ICacheFactory $cacheFactory,
47
-								IClientService $clientService
48
-	) {
49
-		$this->cache = $cacheFactory->createDistributed('ocs-discovery');
50
-		$this->client = $clientService->newClient();
51
-	}
52
-
53
-
54
-	/**
55
-	 * Discover OCS end-points
56
-	 *
57
-	 * If no valid discovery data is found the defaults are returned
58
-	 *
59
-	 * @param string $remote
60
-	 * @param string $service the service you want to discover
61
-	 * @return array
62
-	 */
63
-	public function discover($remote, $service) {
64
-		// Check the cache first
65
-		$cacheData = $this->cache->get($remote . '#' . $service);
66
-		if($cacheData) {
67
-			return json_decode($cacheData, true);
68
-		}
69
-
70
-		$discoveredServices = [];
71
-
72
-		// query the remote server for available services
73
-		try {
74
-			$response = $this->client->get($remote . '/ocs-provider/', [
75
-				'timeout' => 10,
76
-				'connect_timeout' => 10,
77
-			]);
78
-			if($response->getStatusCode() === Http::STATUS_OK) {
79
-				$decodedServices = json_decode($response->getBody(), true);
80
-				$discoveredServices = $this->getEndpoints($decodedServices, $service);
81
-			}
82
-		} catch (\Exception $e) {
83
-			// if we couldn't discover the service or any end-points we return a empty array
84
-		}
85
-
86
-		// Write into cache
87
-		$this->cache->set($remote . '#' . $service, json_encode($discoveredServices), 60*60*24);
88
-		return $discoveredServices;
89
-	}
90
-
91
-	/**
92
-	 * get requested end-points from the requested service
93
-	 *
94
-	 * @param $decodedServices
95
-	 * @param $service
96
-	 * @return array
97
-	 */
98
-	protected function getEndpoints($decodedServices, $service) {
99
-
100
-		$discoveredServices = [];
101
-
102
-		if(is_array($decodedServices) &&
103
-			isset($decodedServices['services'][$service]['endpoints'])
104
-		) {
105
-			foreach ($decodedServices['services'][$service]['endpoints'] as $endpoint => $url) {
106
-				if($this->isSafeUrl($url)) {
107
-					$discoveredServices[$endpoint] = $url;
108
-				}
109
-			}
110
-		}
111
-
112
-		return $discoveredServices;
113
-	}
114
-
115
-	/**
116
-	 * Returns whether the specified URL includes only safe characters, if not
117
-	 * returns false
118
-	 *
119
-	 * @param string $url
120
-	 * @return bool
121
-	 */
122
-	protected function isSafeUrl($url) {
123
-		return (bool)preg_match('/^[\/\.\-A-Za-z0-9]+$/', $url);
124
-	}
36
+    /** @var ICache */
37
+    private $cache;
38
+
39
+    /** @var IClient */
40
+    private $client;
41
+
42
+    /**
43
+     * @param ICacheFactory $cacheFactory
44
+     * @param IClientService $clientService
45
+     */
46
+    public function __construct(ICacheFactory $cacheFactory,
47
+                                IClientService $clientService
48
+    ) {
49
+        $this->cache = $cacheFactory->createDistributed('ocs-discovery');
50
+        $this->client = $clientService->newClient();
51
+    }
52
+
53
+
54
+    /**
55
+     * Discover OCS end-points
56
+     *
57
+     * If no valid discovery data is found the defaults are returned
58
+     *
59
+     * @param string $remote
60
+     * @param string $service the service you want to discover
61
+     * @return array
62
+     */
63
+    public function discover($remote, $service) {
64
+        // Check the cache first
65
+        $cacheData = $this->cache->get($remote . '#' . $service);
66
+        if($cacheData) {
67
+            return json_decode($cacheData, true);
68
+        }
69
+
70
+        $discoveredServices = [];
71
+
72
+        // query the remote server for available services
73
+        try {
74
+            $response = $this->client->get($remote . '/ocs-provider/', [
75
+                'timeout' => 10,
76
+                'connect_timeout' => 10,
77
+            ]);
78
+            if($response->getStatusCode() === Http::STATUS_OK) {
79
+                $decodedServices = json_decode($response->getBody(), true);
80
+                $discoveredServices = $this->getEndpoints($decodedServices, $service);
81
+            }
82
+        } catch (\Exception $e) {
83
+            // if we couldn't discover the service or any end-points we return a empty array
84
+        }
85
+
86
+        // Write into cache
87
+        $this->cache->set($remote . '#' . $service, json_encode($discoveredServices), 60*60*24);
88
+        return $discoveredServices;
89
+    }
90
+
91
+    /**
92
+     * get requested end-points from the requested service
93
+     *
94
+     * @param $decodedServices
95
+     * @param $service
96
+     * @return array
97
+     */
98
+    protected function getEndpoints($decodedServices, $service) {
99
+
100
+        $discoveredServices = [];
101
+
102
+        if(is_array($decodedServices) &&
103
+            isset($decodedServices['services'][$service]['endpoints'])
104
+        ) {
105
+            foreach ($decodedServices['services'][$service]['endpoints'] as $endpoint => $url) {
106
+                if($this->isSafeUrl($url)) {
107
+                    $discoveredServices[$endpoint] = $url;
108
+                }
109
+            }
110
+        }
111
+
112
+        return $discoveredServices;
113
+    }
114
+
115
+    /**
116
+     * Returns whether the specified URL includes only safe characters, if not
117
+     * returns false
118
+     *
119
+     * @param string $url
120
+     * @return bool
121
+     */
122
+    protected function isSafeUrl($url) {
123
+        return (bool)preg_match('/^[\/\.\-A-Za-z0-9]+$/', $url);
124
+    }
125 125
 
126 126
 }
Please login to merge, or discard this patch.
lib/private/URLGenerator.php 2 patches
Indentation   +204 added lines, -204 removed lines patch added patch discarded remove patch
@@ -46,208 +46,208 @@
 block discarded – undo
46 46
  * Class to generate URLs
47 47
  */
48 48
 class URLGenerator implements IURLGenerator {
49
-	/** @var IConfig */
50
-	private $config;
51
-	/** @var ICacheFactory */
52
-	private $cacheFactory;
53
-	/** @var IRequest */
54
-	private $request;
55
-
56
-	/**
57
-	 * @param IConfig $config
58
-	 * @param ICacheFactory $cacheFactory
59
-	 * @param IRequest $request
60
-	 */
61
-	public function __construct(IConfig $config,
62
-								ICacheFactory $cacheFactory,
63
-								IRequest $request) {
64
-		$this->config = $config;
65
-		$this->cacheFactory = $cacheFactory;
66
-		$this->request = $request;
67
-	}
68
-
69
-	/**
70
-	 * Creates an url using a defined route
71
-	 * @param string $route
72
-	 * @param array $parameters args with param=>value, will be appended to the returned url
73
-	 * @return string the url
74
-	 *
75
-	 * Returns a url to the given route.
76
-	 */
77
-	public function linkToRoute($route, $parameters = array()) {
78
-		// TODO: mock router
79
-		$urlLinkTo = \OC::$server->getRouter()->generate($route, $parameters);
80
-		return $urlLinkTo;
81
-	}
82
-
83
-	/**
84
-	 * Creates an absolute url using a defined route
85
-	 * @param string $routeName
86
-	 * @param array $arguments args with param=>value, will be appended to the returned url
87
-	 * @return string the url
88
-	 *
89
-	 * Returns an absolute url to the given route.
90
-	 */
91
-	public function linkToRouteAbsolute($routeName, $arguments = array()) {
92
-		return $this->getAbsoluteURL($this->linkToRoute($routeName, $arguments));
93
-	}
94
-
95
-	/**
96
-	 * Creates an url
97
-	 * @param string $app app
98
-	 * @param string $file file
99
-	 * @param array $args array with param=>value, will be appended to the returned url
100
-	 *    The value of $args will be urlencoded
101
-	 * @return string the url
102
-	 *
103
-	 * Returns a url to the given app and file.
104
-	 */
105
-	public function linkTo( $app, $file, $args = array() ) {
106
-		$frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
107
-
108
-		if( $app != '' ) {
109
-			$app_path = \OC_App::getAppPath($app);
110
-			// Check if the app is in the app folder
111
-			if ($app_path && file_exists($app_path . '/' . $file)) {
112
-				if (substr($file, -3) == 'php') {
113
-
114
-					$urlLinkTo = \OC::$WEBROOT . '/index.php/apps/' . $app;
115
-					if ($frontControllerActive) {
116
-						$urlLinkTo = \OC::$WEBROOT . '/apps/' . $app;
117
-					}
118
-					$urlLinkTo .= ($file != 'index.php') ? '/' . $file : '';
119
-				} else {
120
-					$urlLinkTo = \OC_App::getAppWebPath($app) . '/' . $file;
121
-				}
122
-			} else {
123
-				$urlLinkTo = \OC::$WEBROOT . '/' . $app . '/' . $file;
124
-			}
125
-		} else {
126
-			if (file_exists(\OC::$SERVERROOT . '/core/' . $file)) {
127
-				$urlLinkTo = \OC::$WEBROOT . '/core/' . $file;
128
-			} else {
129
-				if ($frontControllerActive && $file === 'index.php') {
130
-					$urlLinkTo = \OC::$WEBROOT . '/';
131
-				} else {
132
-					$urlLinkTo = \OC::$WEBROOT . '/' . $file;
133
-				}
134
-			}
135
-		}
136
-
137
-		if ($args && $query = http_build_query($args, '', '&')) {
138
-			$urlLinkTo .= '?' . $query;
139
-		}
140
-
141
-		return $urlLinkTo;
142
-	}
143
-
144
-	/**
145
-	 * Creates path to an image
146
-	 * @param string $app app
147
-	 * @param string $image image name
148
-	 * @throws \RuntimeException If the image does not exist
149
-	 * @return string the url
150
-	 *
151
-	 * Returns the path to the image.
152
-	 */
153
-	public function imagePath($app, $image) {
154
-		$cache = $this->cacheFactory->createDistributed('imagePath-'.md5($this->getBaseUrl()).'-');
155
-		$cacheKey = $app.'-'.$image;
156
-		if($key = $cache->get($cacheKey)) {
157
-			return $key;
158
-		}
159
-
160
-		// Read the selected theme from the config file
161
-		$theme = \OC_Util::getTheme();
162
-
163
-		//if a theme has a png but not an svg always use the png
164
-		$basename = substr(basename($image),0,-4);
165
-
166
-		$appPath = \OC_App::getAppPath($app);
167
-
168
-		// Check if the app is in the app folder
169
-		$path = '';
170
-		$themingEnabled = $this->config->getSystemValue('installed', false) && \OCP\App::isEnabled('theming') && \OC_App::isAppLoaded('theming');
171
-		$themingImagePath = false;
172
-		if($themingEnabled) {
173
-			$themingImagePath = \OC::$server->getThemingDefaults()->replaceImagePath($app, $image);
174
-		}
175
-
176
-		if (file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) {
177
-			$path = \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$image";
178
-		} elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.svg")
179
-			&& file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.png")) {
180
-			$path =  \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$basename.png";
181
-		} elseif (!empty($app) and file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$image")) {
182
-			$path =  \OC::$WEBROOT . "/themes/$theme/$app/img/$image";
183
-		} elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$basename.svg")
184
-			&& file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$basename.png"))) {
185
-			$path =  \OC::$WEBROOT . "/themes/$theme/$app/img/$basename.png";
186
-		} elseif (file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$image")) {
187
-			$path =  \OC::$WEBROOT . "/themes/$theme/core/img/$image";
188
-		} elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.svg")
189
-			&& file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.png")) {
190
-			$path =  \OC::$WEBROOT . "/themes/$theme/core/img/$basename.png";
191
-		} elseif($themingEnabled && $themingImagePath) {
192
-			$path = $themingImagePath;
193
-		} elseif ($appPath && file_exists($appPath . "/img/$image")) {
194
-			$path =  \OC_App::getAppWebPath($app) . "/img/$image";
195
-		} elseif ($appPath && !file_exists($appPath . "/img/$basename.svg")
196
-			&& file_exists($appPath . "/img/$basename.png")) {
197
-			$path =  \OC_App::getAppWebPath($app) . "/img/$basename.png";
198
-		} elseif (!empty($app) and file_exists(\OC::$SERVERROOT . "/$app/img/$image")) {
199
-			$path =  \OC::$WEBROOT . "/$app/img/$image";
200
-		} elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT . "/$app/img/$basename.svg")
201
-				&& file_exists(\OC::$SERVERROOT . "/$app/img/$basename.png"))) {
202
-			$path =  \OC::$WEBROOT . "/$app/img/$basename.png";
203
-		} elseif (file_exists(\OC::$SERVERROOT . "/core/img/$image")) {
204
-			$path =  \OC::$WEBROOT . "/core/img/$image";
205
-		} elseif (!file_exists(\OC::$SERVERROOT . "/core/img/$basename.svg")
206
-			&& file_exists(\OC::$SERVERROOT . "/core/img/$basename.png")) {
207
-			$path =  \OC::$WEBROOT . "/themes/$theme/core/img/$basename.png";
208
-		}
209
-
210
-		if($path !== '') {
211
-			$cache->set($cacheKey, $path);
212
-			return $path;
213
-		} else {
214
-			throw new RuntimeException('image not found: image:' . $image . ' webroot:' . \OC::$WEBROOT . ' serverroot:' . \OC::$SERVERROOT);
215
-		}
216
-	}
217
-
218
-
219
-	/**
220
-	 * Makes an URL absolute
221
-	 * @param string $url the url in the ownCloud host
222
-	 * @return string the absolute version of the url
223
-	 */
224
-	public function getAbsoluteURL($url) {
225
-		$separator = $url[0] === '/' ? '' : '/';
226
-
227
-		if (\OC::$CLI && !defined('PHPUNIT_RUN')) {
228
-			return rtrim($this->config->getSystemValue('overwrite.cli.url'), '/') . '/' . ltrim($url, '/');
229
-		}
230
-		// The ownCloud web root can already be prepended.
231
-		if(substr($url, 0, strlen(\OC::$WEBROOT)) === \OC::$WEBROOT) {
232
-			$url = substr($url, strlen(\OC::$WEBROOT));
233
-		}
234
-
235
-		return $this->getBaseUrl() . $separator . $url;
236
-	}
237
-
238
-	/**
239
-	 * @param string $key
240
-	 * @return string url to the online documentation
241
-	 */
242
-	public function linkToDocs($key) {
243
-		$theme = \OC::$server->getThemingDefaults();
244
-		return $theme->buildDocLinkToKey($key);
245
-	}
246
-
247
-	/**
248
-	 * @return string base url of the current request
249
-	 */
250
-	public function getBaseUrl() {
251
-		return $this->request->getServerProtocol() . '://' . $this->request->getServerHost() . \OC::$WEBROOT;
252
-	}
49
+    /** @var IConfig */
50
+    private $config;
51
+    /** @var ICacheFactory */
52
+    private $cacheFactory;
53
+    /** @var IRequest */
54
+    private $request;
55
+
56
+    /**
57
+     * @param IConfig $config
58
+     * @param ICacheFactory $cacheFactory
59
+     * @param IRequest $request
60
+     */
61
+    public function __construct(IConfig $config,
62
+                                ICacheFactory $cacheFactory,
63
+                                IRequest $request) {
64
+        $this->config = $config;
65
+        $this->cacheFactory = $cacheFactory;
66
+        $this->request = $request;
67
+    }
68
+
69
+    /**
70
+     * Creates an url using a defined route
71
+     * @param string $route
72
+     * @param array $parameters args with param=>value, will be appended to the returned url
73
+     * @return string the url
74
+     *
75
+     * Returns a url to the given route.
76
+     */
77
+    public function linkToRoute($route, $parameters = array()) {
78
+        // TODO: mock router
79
+        $urlLinkTo = \OC::$server->getRouter()->generate($route, $parameters);
80
+        return $urlLinkTo;
81
+    }
82
+
83
+    /**
84
+     * Creates an absolute url using a defined route
85
+     * @param string $routeName
86
+     * @param array $arguments args with param=>value, will be appended to the returned url
87
+     * @return string the url
88
+     *
89
+     * Returns an absolute url to the given route.
90
+     */
91
+    public function linkToRouteAbsolute($routeName, $arguments = array()) {
92
+        return $this->getAbsoluteURL($this->linkToRoute($routeName, $arguments));
93
+    }
94
+
95
+    /**
96
+     * Creates an url
97
+     * @param string $app app
98
+     * @param string $file file
99
+     * @param array $args array with param=>value, will be appended to the returned url
100
+     *    The value of $args will be urlencoded
101
+     * @return string the url
102
+     *
103
+     * Returns a url to the given app and file.
104
+     */
105
+    public function linkTo( $app, $file, $args = array() ) {
106
+        $frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
107
+
108
+        if( $app != '' ) {
109
+            $app_path = \OC_App::getAppPath($app);
110
+            // Check if the app is in the app folder
111
+            if ($app_path && file_exists($app_path . '/' . $file)) {
112
+                if (substr($file, -3) == 'php') {
113
+
114
+                    $urlLinkTo = \OC::$WEBROOT . '/index.php/apps/' . $app;
115
+                    if ($frontControllerActive) {
116
+                        $urlLinkTo = \OC::$WEBROOT . '/apps/' . $app;
117
+                    }
118
+                    $urlLinkTo .= ($file != 'index.php') ? '/' . $file : '';
119
+                } else {
120
+                    $urlLinkTo = \OC_App::getAppWebPath($app) . '/' . $file;
121
+                }
122
+            } else {
123
+                $urlLinkTo = \OC::$WEBROOT . '/' . $app . '/' . $file;
124
+            }
125
+        } else {
126
+            if (file_exists(\OC::$SERVERROOT . '/core/' . $file)) {
127
+                $urlLinkTo = \OC::$WEBROOT . '/core/' . $file;
128
+            } else {
129
+                if ($frontControllerActive && $file === 'index.php') {
130
+                    $urlLinkTo = \OC::$WEBROOT . '/';
131
+                } else {
132
+                    $urlLinkTo = \OC::$WEBROOT . '/' . $file;
133
+                }
134
+            }
135
+        }
136
+
137
+        if ($args && $query = http_build_query($args, '', '&')) {
138
+            $urlLinkTo .= '?' . $query;
139
+        }
140
+
141
+        return $urlLinkTo;
142
+    }
143
+
144
+    /**
145
+     * Creates path to an image
146
+     * @param string $app app
147
+     * @param string $image image name
148
+     * @throws \RuntimeException If the image does not exist
149
+     * @return string the url
150
+     *
151
+     * Returns the path to the image.
152
+     */
153
+    public function imagePath($app, $image) {
154
+        $cache = $this->cacheFactory->createDistributed('imagePath-'.md5($this->getBaseUrl()).'-');
155
+        $cacheKey = $app.'-'.$image;
156
+        if($key = $cache->get($cacheKey)) {
157
+            return $key;
158
+        }
159
+
160
+        // Read the selected theme from the config file
161
+        $theme = \OC_Util::getTheme();
162
+
163
+        //if a theme has a png but not an svg always use the png
164
+        $basename = substr(basename($image),0,-4);
165
+
166
+        $appPath = \OC_App::getAppPath($app);
167
+
168
+        // Check if the app is in the app folder
169
+        $path = '';
170
+        $themingEnabled = $this->config->getSystemValue('installed', false) && \OCP\App::isEnabled('theming') && \OC_App::isAppLoaded('theming');
171
+        $themingImagePath = false;
172
+        if($themingEnabled) {
173
+            $themingImagePath = \OC::$server->getThemingDefaults()->replaceImagePath($app, $image);
174
+        }
175
+
176
+        if (file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) {
177
+            $path = \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$image";
178
+        } elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.svg")
179
+            && file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.png")) {
180
+            $path =  \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$basename.png";
181
+        } elseif (!empty($app) and file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$image")) {
182
+            $path =  \OC::$WEBROOT . "/themes/$theme/$app/img/$image";
183
+        } elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$basename.svg")
184
+            && file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$basename.png"))) {
185
+            $path =  \OC::$WEBROOT . "/themes/$theme/$app/img/$basename.png";
186
+        } elseif (file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$image")) {
187
+            $path =  \OC::$WEBROOT . "/themes/$theme/core/img/$image";
188
+        } elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.svg")
189
+            && file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.png")) {
190
+            $path =  \OC::$WEBROOT . "/themes/$theme/core/img/$basename.png";
191
+        } elseif($themingEnabled && $themingImagePath) {
192
+            $path = $themingImagePath;
193
+        } elseif ($appPath && file_exists($appPath . "/img/$image")) {
194
+            $path =  \OC_App::getAppWebPath($app) . "/img/$image";
195
+        } elseif ($appPath && !file_exists($appPath . "/img/$basename.svg")
196
+            && file_exists($appPath . "/img/$basename.png")) {
197
+            $path =  \OC_App::getAppWebPath($app) . "/img/$basename.png";
198
+        } elseif (!empty($app) and file_exists(\OC::$SERVERROOT . "/$app/img/$image")) {
199
+            $path =  \OC::$WEBROOT . "/$app/img/$image";
200
+        } elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT . "/$app/img/$basename.svg")
201
+                && file_exists(\OC::$SERVERROOT . "/$app/img/$basename.png"))) {
202
+            $path =  \OC::$WEBROOT . "/$app/img/$basename.png";
203
+        } elseif (file_exists(\OC::$SERVERROOT . "/core/img/$image")) {
204
+            $path =  \OC::$WEBROOT . "/core/img/$image";
205
+        } elseif (!file_exists(\OC::$SERVERROOT . "/core/img/$basename.svg")
206
+            && file_exists(\OC::$SERVERROOT . "/core/img/$basename.png")) {
207
+            $path =  \OC::$WEBROOT . "/themes/$theme/core/img/$basename.png";
208
+        }
209
+
210
+        if($path !== '') {
211
+            $cache->set($cacheKey, $path);
212
+            return $path;
213
+        } else {
214
+            throw new RuntimeException('image not found: image:' . $image . ' webroot:' . \OC::$WEBROOT . ' serverroot:' . \OC::$SERVERROOT);
215
+        }
216
+    }
217
+
218
+
219
+    /**
220
+     * Makes an URL absolute
221
+     * @param string $url the url in the ownCloud host
222
+     * @return string the absolute version of the url
223
+     */
224
+    public function getAbsoluteURL($url) {
225
+        $separator = $url[0] === '/' ? '' : '/';
226
+
227
+        if (\OC::$CLI && !defined('PHPUNIT_RUN')) {
228
+            return rtrim($this->config->getSystemValue('overwrite.cli.url'), '/') . '/' . ltrim($url, '/');
229
+        }
230
+        // The ownCloud web root can already be prepended.
231
+        if(substr($url, 0, strlen(\OC::$WEBROOT)) === \OC::$WEBROOT) {
232
+            $url = substr($url, strlen(\OC::$WEBROOT));
233
+        }
234
+
235
+        return $this->getBaseUrl() . $separator . $url;
236
+    }
237
+
238
+    /**
239
+     * @param string $key
240
+     * @return string url to the online documentation
241
+     */
242
+    public function linkToDocs($key) {
243
+        $theme = \OC::$server->getThemingDefaults();
244
+        return $theme->buildDocLinkToKey($key);
245
+    }
246
+
247
+    /**
248
+     * @return string base url of the current request
249
+     */
250
+    public function getBaseUrl() {
251
+        return $this->request->getServerProtocol() . '://' . $this->request->getServerHost() . \OC::$WEBROOT;
252
+    }
253 253
 }
Please login to merge, or discard this patch.
Spacing   +53 added lines, -53 removed lines patch added patch discarded remove patch
@@ -102,40 +102,40 @@  discard block
 block discarded – undo
102 102
 	 *
103 103
 	 * Returns a url to the given app and file.
104 104
 	 */
105
-	public function linkTo( $app, $file, $args = array() ) {
105
+	public function linkTo($app, $file, $args = array()) {
106 106
 		$frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
107 107
 
108
-		if( $app != '' ) {
108
+		if ($app != '') {
109 109
 			$app_path = \OC_App::getAppPath($app);
110 110
 			// Check if the app is in the app folder
111
-			if ($app_path && file_exists($app_path . '/' . $file)) {
111
+			if ($app_path && file_exists($app_path.'/'.$file)) {
112 112
 				if (substr($file, -3) == 'php') {
113 113
 
114
-					$urlLinkTo = \OC::$WEBROOT . '/index.php/apps/' . $app;
114
+					$urlLinkTo = \OC::$WEBROOT.'/index.php/apps/'.$app;
115 115
 					if ($frontControllerActive) {
116
-						$urlLinkTo = \OC::$WEBROOT . '/apps/' . $app;
116
+						$urlLinkTo = \OC::$WEBROOT.'/apps/'.$app;
117 117
 					}
118
-					$urlLinkTo .= ($file != 'index.php') ? '/' . $file : '';
118
+					$urlLinkTo .= ($file != 'index.php') ? '/'.$file : '';
119 119
 				} else {
120
-					$urlLinkTo = \OC_App::getAppWebPath($app) . '/' . $file;
120
+					$urlLinkTo = \OC_App::getAppWebPath($app).'/'.$file;
121 121
 				}
122 122
 			} else {
123
-				$urlLinkTo = \OC::$WEBROOT . '/' . $app . '/' . $file;
123
+				$urlLinkTo = \OC::$WEBROOT.'/'.$app.'/'.$file;
124 124
 			}
125 125
 		} else {
126
-			if (file_exists(\OC::$SERVERROOT . '/core/' . $file)) {
127
-				$urlLinkTo = \OC::$WEBROOT . '/core/' . $file;
126
+			if (file_exists(\OC::$SERVERROOT.'/core/'.$file)) {
127
+				$urlLinkTo = \OC::$WEBROOT.'/core/'.$file;
128 128
 			} else {
129 129
 				if ($frontControllerActive && $file === 'index.php') {
130
-					$urlLinkTo = \OC::$WEBROOT . '/';
130
+					$urlLinkTo = \OC::$WEBROOT.'/';
131 131
 				} else {
132
-					$urlLinkTo = \OC::$WEBROOT . '/' . $file;
132
+					$urlLinkTo = \OC::$WEBROOT.'/'.$file;
133 133
 				}
134 134
 			}
135 135
 		}
136 136
 
137 137
 		if ($args && $query = http_build_query($args, '', '&')) {
138
-			$urlLinkTo .= '?' . $query;
138
+			$urlLinkTo .= '?'.$query;
139 139
 		}
140 140
 
141 141
 		return $urlLinkTo;
@@ -153,7 +153,7 @@  discard block
 block discarded – undo
153 153
 	public function imagePath($app, $image) {
154 154
 		$cache = $this->cacheFactory->createDistributed('imagePath-'.md5($this->getBaseUrl()).'-');
155 155
 		$cacheKey = $app.'-'.$image;
156
-		if($key = $cache->get($cacheKey)) {
156
+		if ($key = $cache->get($cacheKey)) {
157 157
 			return $key;
158 158
 		}
159 159
 
@@ -161,7 +161,7 @@  discard block
 block discarded – undo
161 161
 		$theme = \OC_Util::getTheme();
162 162
 
163 163
 		//if a theme has a png but not an svg always use the png
164
-		$basename = substr(basename($image),0,-4);
164
+		$basename = substr(basename($image), 0, -4);
165 165
 
166 166
 		$appPath = \OC_App::getAppPath($app);
167 167
 
@@ -169,49 +169,49 @@  discard block
 block discarded – undo
169 169
 		$path = '';
170 170
 		$themingEnabled = $this->config->getSystemValue('installed', false) && \OCP\App::isEnabled('theming') && \OC_App::isAppLoaded('theming');
171 171
 		$themingImagePath = false;
172
-		if($themingEnabled) {
172
+		if ($themingEnabled) {
173 173
 			$themingImagePath = \OC::$server->getThemingDefaults()->replaceImagePath($app, $image);
174 174
 		}
175 175
 
176
-		if (file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) {
177
-			$path = \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$image";
178
-		} elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.svg")
179
-			&& file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.png")) {
180
-			$path =  \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$basename.png";
181
-		} elseif (!empty($app) and file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$image")) {
182
-			$path =  \OC::$WEBROOT . "/themes/$theme/$app/img/$image";
183
-		} elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$basename.svg")
184
-			&& file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$basename.png"))) {
185
-			$path =  \OC::$WEBROOT . "/themes/$theme/$app/img/$basename.png";
186
-		} elseif (file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$image")) {
187
-			$path =  \OC::$WEBROOT . "/themes/$theme/core/img/$image";
188
-		} elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.svg")
189
-			&& file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.png")) {
190
-			$path =  \OC::$WEBROOT . "/themes/$theme/core/img/$basename.png";
191
-		} elseif($themingEnabled && $themingImagePath) {
176
+		if (file_exists(\OC::$SERVERROOT."/themes/$theme/apps/$app/img/$image")) {
177
+			$path = \OC::$WEBROOT."/themes/$theme/apps/$app/img/$image";
178
+		} elseif (!file_exists(\OC::$SERVERROOT."/themes/$theme/apps/$app/img/$basename.svg")
179
+			&& file_exists(\OC::$SERVERROOT."/themes/$theme/apps/$app/img/$basename.png")) {
180
+			$path = \OC::$WEBROOT."/themes/$theme/apps/$app/img/$basename.png";
181
+		} elseif (!empty($app) and file_exists(\OC::$SERVERROOT."/themes/$theme/$app/img/$image")) {
182
+			$path = \OC::$WEBROOT."/themes/$theme/$app/img/$image";
183
+		} elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT."/themes/$theme/$app/img/$basename.svg")
184
+			&& file_exists(\OC::$SERVERROOT."/themes/$theme/$app/img/$basename.png"))) {
185
+			$path = \OC::$WEBROOT."/themes/$theme/$app/img/$basename.png";
186
+		} elseif (file_exists(\OC::$SERVERROOT."/themes/$theme/core/img/$image")) {
187
+			$path = \OC::$WEBROOT."/themes/$theme/core/img/$image";
188
+		} elseif (!file_exists(\OC::$SERVERROOT."/themes/$theme/core/img/$basename.svg")
189
+			&& file_exists(\OC::$SERVERROOT."/themes/$theme/core/img/$basename.png")) {
190
+			$path = \OC::$WEBROOT."/themes/$theme/core/img/$basename.png";
191
+		} elseif ($themingEnabled && $themingImagePath) {
192 192
 			$path = $themingImagePath;
193
-		} elseif ($appPath && file_exists($appPath . "/img/$image")) {
194
-			$path =  \OC_App::getAppWebPath($app) . "/img/$image";
195
-		} elseif ($appPath && !file_exists($appPath . "/img/$basename.svg")
196
-			&& file_exists($appPath . "/img/$basename.png")) {
197
-			$path =  \OC_App::getAppWebPath($app) . "/img/$basename.png";
198
-		} elseif (!empty($app) and file_exists(\OC::$SERVERROOT . "/$app/img/$image")) {
199
-			$path =  \OC::$WEBROOT . "/$app/img/$image";
200
-		} elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT . "/$app/img/$basename.svg")
201
-				&& file_exists(\OC::$SERVERROOT . "/$app/img/$basename.png"))) {
202
-			$path =  \OC::$WEBROOT . "/$app/img/$basename.png";
203
-		} elseif (file_exists(\OC::$SERVERROOT . "/core/img/$image")) {
204
-			$path =  \OC::$WEBROOT . "/core/img/$image";
205
-		} elseif (!file_exists(\OC::$SERVERROOT . "/core/img/$basename.svg")
206
-			&& file_exists(\OC::$SERVERROOT . "/core/img/$basename.png")) {
207
-			$path =  \OC::$WEBROOT . "/themes/$theme/core/img/$basename.png";
193
+		} elseif ($appPath && file_exists($appPath."/img/$image")) {
194
+			$path = \OC_App::getAppWebPath($app)."/img/$image";
195
+		} elseif ($appPath && !file_exists($appPath."/img/$basename.svg")
196
+			&& file_exists($appPath."/img/$basename.png")) {
197
+			$path = \OC_App::getAppWebPath($app)."/img/$basename.png";
198
+		} elseif (!empty($app) and file_exists(\OC::$SERVERROOT."/$app/img/$image")) {
199
+			$path = \OC::$WEBROOT."/$app/img/$image";
200
+		} elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT."/$app/img/$basename.svg")
201
+				&& file_exists(\OC::$SERVERROOT."/$app/img/$basename.png"))) {
202
+			$path = \OC::$WEBROOT."/$app/img/$basename.png";
203
+		} elseif (file_exists(\OC::$SERVERROOT."/core/img/$image")) {
204
+			$path = \OC::$WEBROOT."/core/img/$image";
205
+		} elseif (!file_exists(\OC::$SERVERROOT."/core/img/$basename.svg")
206
+			&& file_exists(\OC::$SERVERROOT."/core/img/$basename.png")) {
207
+			$path = \OC::$WEBROOT."/themes/$theme/core/img/$basename.png";
208 208
 		}
209 209
 
210
-		if($path !== '') {
210
+		if ($path !== '') {
211 211
 			$cache->set($cacheKey, $path);
212 212
 			return $path;
213 213
 		} else {
214
-			throw new RuntimeException('image not found: image:' . $image . ' webroot:' . \OC::$WEBROOT . ' serverroot:' . \OC::$SERVERROOT);
214
+			throw new RuntimeException('image not found: image:'.$image.' webroot:'.\OC::$WEBROOT.' serverroot:'.\OC::$SERVERROOT);
215 215
 		}
216 216
 	}
217 217
 
@@ -225,14 +225,14 @@  discard block
 block discarded – undo
225 225
 		$separator = $url[0] === '/' ? '' : '/';
226 226
 
227 227
 		if (\OC::$CLI && !defined('PHPUNIT_RUN')) {
228
-			return rtrim($this->config->getSystemValue('overwrite.cli.url'), '/') . '/' . ltrim($url, '/');
228
+			return rtrim($this->config->getSystemValue('overwrite.cli.url'), '/').'/'.ltrim($url, '/');
229 229
 		}
230 230
 		// The ownCloud web root can already be prepended.
231
-		if(substr($url, 0, strlen(\OC::$WEBROOT)) === \OC::$WEBROOT) {
231
+		if (substr($url, 0, strlen(\OC::$WEBROOT)) === \OC::$WEBROOT) {
232 232
 			$url = substr($url, strlen(\OC::$WEBROOT));
233 233
 		}
234 234
 
235
-		return $this->getBaseUrl() . $separator . $url;
235
+		return $this->getBaseUrl().$separator.$url;
236 236
 	}
237 237
 
238 238
 	/**
@@ -248,6 +248,6 @@  discard block
 block discarded – undo
248 248
 	 * @return string base url of the current request
249 249
 	 */
250 250
 	public function getBaseUrl() {
251
-		return $this->request->getServerProtocol() . '://' . $this->request->getServerHost() . \OC::$WEBROOT;
251
+		return $this->request->getServerProtocol().'://'.$this->request->getServerHost().\OC::$WEBROOT;
252 252
 	}
253 253
 }
Please login to merge, or discard this patch.
lib/private/IntegrityCheck/Checker.php 1 patch
Indentation   +551 added lines, -551 removed lines patch added patch discarded remove patch
@@ -51,555 +51,555 @@
 block discarded – undo
51 51
  * @package OC\IntegrityCheck
52 52
  */
53 53
 class Checker {
54
-	const CACHE_KEY = 'oc.integritycheck.checker';
55
-	/** @var EnvironmentHelper */
56
-	private $environmentHelper;
57
-	/** @var AppLocator */
58
-	private $appLocator;
59
-	/** @var FileAccessHelper */
60
-	private $fileAccessHelper;
61
-	/** @var IConfig */
62
-	private $config;
63
-	/** @var ICache */
64
-	private $cache;
65
-	/** @var IAppManager */
66
-	private $appManager;
67
-	/** @var ITempManager */
68
-	private $tempManager;
69
-
70
-	/**
71
-	 * @param EnvironmentHelper $environmentHelper
72
-	 * @param FileAccessHelper $fileAccessHelper
73
-	 * @param AppLocator $appLocator
74
-	 * @param IConfig $config
75
-	 * @param ICacheFactory $cacheFactory
76
-	 * @param IAppManager $appManager
77
-	 * @param ITempManager $tempManager
78
-	 */
79
-	public function __construct(EnvironmentHelper $environmentHelper,
80
-								FileAccessHelper $fileAccessHelper,
81
-								AppLocator $appLocator,
82
-								IConfig $config = null,
83
-								ICacheFactory $cacheFactory,
84
-								IAppManager $appManager = null,
85
-								ITempManager $tempManager) {
86
-		$this->environmentHelper = $environmentHelper;
87
-		$this->fileAccessHelper = $fileAccessHelper;
88
-		$this->appLocator = $appLocator;
89
-		$this->config = $config;
90
-		$this->cache = $cacheFactory->createDistributed(self::CACHE_KEY);
91
-		$this->appManager = $appManager;
92
-		$this->tempManager = $tempManager;
93
-	}
94
-
95
-	/**
96
-	 * Whether code signing is enforced or not.
97
-	 *
98
-	 * @return bool
99
-	 */
100
-	public function isCodeCheckEnforced() {
101
-		$notSignedChannels = [ '', 'git'];
102
-		if (in_array($this->environmentHelper->getChannel(), $notSignedChannels, true)) {
103
-			return false;
104
-		}
105
-
106
-		/**
107
-		 * This config option is undocumented and supposed to be so, it's only
108
-		 * applicable for very specific scenarios and we should not advertise it
109
-		 * too prominent. So please do not add it to config.sample.php.
110
-		 */
111
-		if ($this->config !== null) {
112
-			$isIntegrityCheckDisabled = $this->config->getSystemValue('integrity.check.disabled', false);
113
-		} else {
114
-			$isIntegrityCheckDisabled = false;
115
-		}
116
-		if ($isIntegrityCheckDisabled === true) {
117
-			return false;
118
-		}
119
-
120
-		return true;
121
-	}
122
-
123
-	/**
124
-	 * Enumerates all files belonging to the folder. Sensible defaults are excluded.
125
-	 *
126
-	 * @param string $folderToIterate
127
-	 * @param string $root
128
-	 * @return \RecursiveIteratorIterator
129
-	 * @throws \Exception
130
-	 */
131
-	private function getFolderIterator($folderToIterate, $root = '') {
132
-		$dirItr = new \RecursiveDirectoryIterator(
133
-			$folderToIterate,
134
-			\RecursiveDirectoryIterator::SKIP_DOTS
135
-		);
136
-		if($root === '') {
137
-			$root = \OC::$SERVERROOT;
138
-		}
139
-		$root = rtrim($root, '/');
140
-
141
-		$excludeGenericFilesIterator = new ExcludeFileByNameFilterIterator($dirItr);
142
-		$excludeFoldersIterator = new ExcludeFoldersByPathFilterIterator($excludeGenericFilesIterator, $root);
143
-
144
-		return new \RecursiveIteratorIterator(
145
-			$excludeFoldersIterator,
146
-			\RecursiveIteratorIterator::SELF_FIRST
147
-		);
148
-	}
149
-
150
-	/**
151
-	 * Returns an array of ['filename' => 'SHA512-hash-of-file'] for all files found
152
-	 * in the iterator.
153
-	 *
154
-	 * @param \RecursiveIteratorIterator $iterator
155
-	 * @param string $path
156
-	 * @return array Array of hashes.
157
-	 */
158
-	private function generateHashes(\RecursiveIteratorIterator $iterator,
159
-									$path) {
160
-		$hashes = [];
161
-		$copiedWebserverSettingFiles = false;
162
-		$tmpFolder = '';
163
-
164
-		$baseDirectoryLength = strlen($path);
165
-		foreach($iterator as $filename => $data) {
166
-			/** @var \DirectoryIterator $data */
167
-			if($data->isDir()) {
168
-				continue;
169
-			}
170
-
171
-			$relativeFileName = substr($filename, $baseDirectoryLength);
172
-			$relativeFileName = ltrim($relativeFileName, '/');
173
-
174
-			// Exclude signature.json files in the appinfo and root folder
175
-			if($relativeFileName === 'appinfo/signature.json') {
176
-				continue;
177
-			}
178
-			// Exclude signature.json files in the appinfo and core folder
179
-			if($relativeFileName === 'core/signature.json') {
180
-				continue;
181
-			}
182
-
183
-			// The .user.ini and the .htaccess file of ownCloud can contain some
184
-			// custom modifications such as for example the maximum upload size
185
-			// to ensure that this will not lead to false positives this will
186
-			// copy the file to a temporary folder and reset it to the default
187
-			// values.
188
-			if($filename === $this->environmentHelper->getServerRoot() . '/.htaccess'
189
-				|| $filename === $this->environmentHelper->getServerRoot() . '/.user.ini') {
190
-
191
-				if(!$copiedWebserverSettingFiles) {
192
-					$tmpFolder = rtrim($this->tempManager->getTemporaryFolder(), '/');
193
-					copy($this->environmentHelper->getServerRoot() . '/.htaccess', $tmpFolder . '/.htaccess');
194
-					copy($this->environmentHelper->getServerRoot() . '/.user.ini', $tmpFolder . '/.user.ini');
195
-					\OC_Files::setUploadLimit(
196
-						\OCP\Util::computerFileSize('511MB'),
197
-						[
198
-							'.htaccess' => $tmpFolder . '/.htaccess',
199
-							'.user.ini' => $tmpFolder . '/.user.ini',
200
-						]
201
-					);
202
-				}
203
-			}
204
-
205
-			// The .user.ini file can contain custom modifications to the file size
206
-			// as well.
207
-			if($filename === $this->environmentHelper->getServerRoot() . '/.user.ini') {
208
-				$fileContent = file_get_contents($tmpFolder . '/.user.ini');
209
-				$hashes[$relativeFileName] = hash('sha512', $fileContent);
210
-				continue;
211
-			}
212
-
213
-			// The .htaccess file in the root folder of ownCloud can contain
214
-			// custom content after the installation due to the fact that dynamic
215
-			// content is written into it at installation time as well. This
216
-			// includes for example the 404 and 403 instructions.
217
-			// Thus we ignore everything below the first occurrence of
218
-			// "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####" and have the
219
-			// hash generated based on this.
220
-			if($filename === $this->environmentHelper->getServerRoot() . '/.htaccess') {
221
-				$fileContent = file_get_contents($tmpFolder . '/.htaccess');
222
-				$explodedArray = explode('#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####', $fileContent);
223
-				if(count($explodedArray) === 2) {
224
-					$hashes[$relativeFileName] = hash('sha512', $explodedArray[0]);
225
-					continue;
226
-				}
227
-			}
228
-
229
-			$hashes[$relativeFileName] = hash_file('sha512', $filename);
230
-		}
231
-
232
-		return $hashes;
233
-	}
234
-
235
-	/**
236
-	 * Creates the signature data
237
-	 *
238
-	 * @param array $hashes
239
-	 * @param X509 $certificate
240
-	 * @param RSA $privateKey
241
-	 * @return string
242
-	 */
243
-	private function createSignatureData(array $hashes,
244
-										 X509 $certificate,
245
-										 RSA $privateKey) {
246
-		ksort($hashes);
247
-
248
-		$privateKey->setSignatureMode(RSA::SIGNATURE_PSS);
249
-		$privateKey->setMGFHash('sha512');
250
-		// See https://tools.ietf.org/html/rfc3447#page-38
251
-		$privateKey->setSaltLength(0);
252
-		$signature = $privateKey->sign(json_encode($hashes));
253
-
254
-		return [
255
-				'hashes' => $hashes,
256
-				'signature' => base64_encode($signature),
257
-				'certificate' => $certificate->saveX509($certificate->currentCert),
258
-			];
259
-	}
260
-
261
-	/**
262
-	 * Write the signature of the app in the specified folder
263
-	 *
264
-	 * @param string $path
265
-	 * @param X509 $certificate
266
-	 * @param RSA $privateKey
267
-	 * @throws \Exception
268
-	 */
269
-	public function writeAppSignature($path,
270
-									  X509 $certificate,
271
-									  RSA $privateKey) {
272
-		$appInfoDir = $path . '/appinfo';
273
-		try {
274
-			$this->fileAccessHelper->assertDirectoryExists($appInfoDir);
275
-
276
-			$iterator = $this->getFolderIterator($path);
277
-			$hashes = $this->generateHashes($iterator, $path);
278
-			$signature = $this->createSignatureData($hashes, $certificate, $privateKey);
279
-				$this->fileAccessHelper->file_put_contents(
280
-					$appInfoDir . '/signature.json',
281
-				json_encode($signature, JSON_PRETTY_PRINT)
282
-			);
283
-		} catch (\Exception $e){
284
-			if (!$this->fileAccessHelper->is_writable($appInfoDir)) {
285
-				throw new \Exception($appInfoDir . ' is not writable');
286
-			}
287
-			throw $e;
288
-		}
289
-	}
290
-
291
-	/**
292
-	 * Write the signature of core
293
-	 *
294
-	 * @param X509 $certificate
295
-	 * @param RSA $rsa
296
-	 * @param string $path
297
-	 * @throws \Exception
298
-	 */
299
-	public function writeCoreSignature(X509 $certificate,
300
-									   RSA $rsa,
301
-									   $path) {
302
-		$coreDir = $path . '/core';
303
-		try {
304
-
305
-			$this->fileAccessHelper->assertDirectoryExists($coreDir);
306
-			$iterator = $this->getFolderIterator($path, $path);
307
-			$hashes = $this->generateHashes($iterator, $path);
308
-			$signatureData = $this->createSignatureData($hashes, $certificate, $rsa);
309
-			$this->fileAccessHelper->file_put_contents(
310
-				$coreDir . '/signature.json',
311
-				json_encode($signatureData, JSON_PRETTY_PRINT)
312
-			);
313
-		} catch (\Exception $e){
314
-			if (!$this->fileAccessHelper->is_writable($coreDir)) {
315
-				throw new \Exception($coreDir . ' is not writable');
316
-			}
317
-			throw $e;
318
-		}
319
-	}
320
-
321
-	/**
322
-	 * Verifies the signature for the specified path.
323
-	 *
324
-	 * @param string $signaturePath
325
-	 * @param string $basePath
326
-	 * @param string $certificateCN
327
-	 * @return array
328
-	 * @throws InvalidSignatureException
329
-	 * @throws \Exception
330
-	 */
331
-	private function verify($signaturePath, $basePath, $certificateCN) {
332
-		if(!$this->isCodeCheckEnforced()) {
333
-			return [];
334
-		}
335
-
336
-		$signatureData = json_decode($this->fileAccessHelper->file_get_contents($signaturePath), true);
337
-		if(!is_array($signatureData)) {
338
-			throw new InvalidSignatureException('Signature data not found.');
339
-		}
340
-
341
-		$expectedHashes = $signatureData['hashes'];
342
-		ksort($expectedHashes);
343
-		$signature = base64_decode($signatureData['signature']);
344
-		$certificate = $signatureData['certificate'];
345
-
346
-		// Check if certificate is signed by Nextcloud Root Authority
347
-		$x509 = new \phpseclib\File\X509();
348
-		$rootCertificatePublicKey = $this->fileAccessHelper->file_get_contents($this->environmentHelper->getServerRoot().'/resources/codesigning/root.crt');
349
-		$x509->loadCA($rootCertificatePublicKey);
350
-		$x509->loadX509($certificate);
351
-		if(!$x509->validateSignature()) {
352
-			throw new InvalidSignatureException('Certificate is not valid.');
353
-		}
354
-		// Verify if certificate has proper CN. "core" CN is always trusted.
355
-		if($x509->getDN(X509::DN_OPENSSL)['CN'] !== $certificateCN && $x509->getDN(X509::DN_OPENSSL)['CN'] !== 'core') {
356
-			throw new InvalidSignatureException(
357
-					sprintf('Certificate is not valid for required scope. (Requested: %s, current: CN=%s)', $certificateCN, $x509->getDN(true)['CN'])
358
-			);
359
-		}
360
-
361
-		// Check if the signature of the files is valid
362
-		$rsa = new \phpseclib\Crypt\RSA();
363
-		$rsa->loadKey($x509->currentCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']);
364
-		$rsa->setSignatureMode(RSA::SIGNATURE_PSS);
365
-		$rsa->setMGFHash('sha512');
366
-		// See https://tools.ietf.org/html/rfc3447#page-38
367
-		$rsa->setSaltLength(0);
368
-		if(!$rsa->verify(json_encode($expectedHashes), $signature)) {
369
-			throw new InvalidSignatureException('Signature could not get verified.');
370
-		}
371
-
372
-		// Fixes for the updater as shipped with ownCloud 9.0.x: The updater is
373
-		// replaced after the code integrity check is performed.
374
-		//
375
-		// Due to this reason we exclude the whole updater/ folder from the code
376
-		// integrity check.
377
-		if($basePath === $this->environmentHelper->getServerRoot()) {
378
-			foreach($expectedHashes as $fileName => $hash) {
379
-				if(strpos($fileName, 'updater/') === 0) {
380
-					unset($expectedHashes[$fileName]);
381
-				}
382
-			}
383
-		}
384
-
385
-		// Compare the list of files which are not identical
386
-		$currentInstanceHashes = $this->generateHashes($this->getFolderIterator($basePath), $basePath);
387
-		$differencesA = array_diff($expectedHashes, $currentInstanceHashes);
388
-		$differencesB = array_diff($currentInstanceHashes, $expectedHashes);
389
-		$differences = array_unique(array_merge($differencesA, $differencesB));
390
-		$differenceArray = [];
391
-		foreach($differences as $filename => $hash) {
392
-			// Check if file should not exist in the new signature table
393
-			if(!array_key_exists($filename, $expectedHashes)) {
394
-				$differenceArray['EXTRA_FILE'][$filename]['expected'] = '';
395
-				$differenceArray['EXTRA_FILE'][$filename]['current'] = $hash;
396
-				continue;
397
-			}
398
-
399
-			// Check if file is missing
400
-			if(!array_key_exists($filename, $currentInstanceHashes)) {
401
-				$differenceArray['FILE_MISSING'][$filename]['expected'] = $expectedHashes[$filename];
402
-				$differenceArray['FILE_MISSING'][$filename]['current'] = '';
403
-				continue;
404
-			}
405
-
406
-			// Check if hash does mismatch
407
-			if($expectedHashes[$filename] !== $currentInstanceHashes[$filename]) {
408
-				$differenceArray['INVALID_HASH'][$filename]['expected'] = $expectedHashes[$filename];
409
-				$differenceArray['INVALID_HASH'][$filename]['current'] = $currentInstanceHashes[$filename];
410
-				continue;
411
-			}
412
-
413
-			// Should never happen.
414
-			throw new \Exception('Invalid behaviour in file hash comparison experienced. Please report this error to the developers.');
415
-		}
416
-
417
-		return $differenceArray;
418
-	}
419
-
420
-	/**
421
-	 * Whether the code integrity check has passed successful or not
422
-	 *
423
-	 * @return bool
424
-	 */
425
-	public function hasPassedCheck() {
426
-		$results = $this->getResults();
427
-		if(empty($results)) {
428
-			return true;
429
-		}
430
-
431
-		return false;
432
-	}
433
-
434
-	/**
435
-	 * @return array
436
-	 */
437
-	public function getResults() {
438
-		$cachedResults = $this->cache->get(self::CACHE_KEY);
439
-		if(!is_null($cachedResults)) {
440
-			return json_decode($cachedResults, true);
441
-		}
442
-
443
-		if ($this->config !== null) {
444
-			return json_decode($this->config->getAppValue('core', self::CACHE_KEY, '{}'), true);
445
-		}
446
-		return [];
447
-	}
448
-
449
-	/**
450
-	 * Stores the results in the app config as well as cache
451
-	 *
452
-	 * @param string $scope
453
-	 * @param array $result
454
-	 */
455
-	private function storeResults($scope, array $result) {
456
-		$resultArray = $this->getResults();
457
-		unset($resultArray[$scope]);
458
-		if(!empty($result)) {
459
-			$resultArray[$scope] = $result;
460
-		}
461
-		if ($this->config !== null) {
462
-			$this->config->setAppValue('core', self::CACHE_KEY, json_encode($resultArray));
463
-		}
464
-		$this->cache->set(self::CACHE_KEY, json_encode($resultArray));
465
-	}
466
-
467
-	/**
468
-	 *
469
-	 * Clean previous results for a proper rescanning. Otherwise
470
-	 */
471
-	private function cleanResults() {
472
-		$this->config->deleteAppValue('core', self::CACHE_KEY);
473
-		$this->cache->remove(self::CACHE_KEY);
474
-	}
475
-
476
-	/**
477
-	 * Verify the signature of $appId. Returns an array with the following content:
478
-	 * [
479
-	 * 	'FILE_MISSING' =>
480
-	 * 	[
481
-	 * 		'filename' => [
482
-	 * 			'expected' => 'expectedSHA512',
483
-	 * 			'current' => 'currentSHA512',
484
-	 * 		],
485
-	 * 	],
486
-	 * 	'EXTRA_FILE' =>
487
-	 * 	[
488
-	 * 		'filename' => [
489
-	 * 			'expected' => 'expectedSHA512',
490
-	 * 			'current' => 'currentSHA512',
491
-	 * 		],
492
-	 * 	],
493
-	 * 	'INVALID_HASH' =>
494
-	 * 	[
495
-	 * 		'filename' => [
496
-	 * 			'expected' => 'expectedSHA512',
497
-	 * 			'current' => 'currentSHA512',
498
-	 * 		],
499
-	 * 	],
500
-	 * ]
501
-	 *
502
-	 * Array may be empty in case no problems have been found.
503
-	 *
504
-	 * @param string $appId
505
-	 * @param string $path Optional path. If none is given it will be guessed.
506
-	 * @return array
507
-	 */
508
-	public function verifyAppSignature($appId, $path = '') {
509
-		try {
510
-			if($path === '') {
511
-				$path = $this->appLocator->getAppPath($appId);
512
-			}
513
-			$result = $this->verify(
514
-					$path . '/appinfo/signature.json',
515
-					$path,
516
-					$appId
517
-			);
518
-		} catch (\Exception $e) {
519
-			$result = [
520
-					'EXCEPTION' => [
521
-							'class' => get_class($e),
522
-							'message' => $e->getMessage(),
523
-					],
524
-			];
525
-		}
526
-		$this->storeResults($appId, $result);
527
-
528
-		return $result;
529
-	}
530
-
531
-	/**
532
-	 * Verify the signature of core. Returns an array with the following content:
533
-	 * [
534
-	 * 	'FILE_MISSING' =>
535
-	 * 	[
536
-	 * 		'filename' => [
537
-	 * 			'expected' => 'expectedSHA512',
538
-	 * 			'current' => 'currentSHA512',
539
-	 * 		],
540
-	 * 	],
541
-	 * 	'EXTRA_FILE' =>
542
-	 * 	[
543
-	 * 		'filename' => [
544
-	 * 			'expected' => 'expectedSHA512',
545
-	 * 			'current' => 'currentSHA512',
546
-	 * 		],
547
-	 * 	],
548
-	 * 	'INVALID_HASH' =>
549
-	 * 	[
550
-	 * 		'filename' => [
551
-	 * 			'expected' => 'expectedSHA512',
552
-	 * 			'current' => 'currentSHA512',
553
-	 * 		],
554
-	 * 	],
555
-	 * ]
556
-	 *
557
-	 * Array may be empty in case no problems have been found.
558
-	 *
559
-	 * @return array
560
-	 */
561
-	public function verifyCoreSignature() {
562
-		try {
563
-			$result = $this->verify(
564
-					$this->environmentHelper->getServerRoot() . '/core/signature.json',
565
-					$this->environmentHelper->getServerRoot(),
566
-					'core'
567
-			);
568
-		} catch (\Exception $e) {
569
-			$result = [
570
-					'EXCEPTION' => [
571
-							'class' => get_class($e),
572
-							'message' => $e->getMessage(),
573
-					],
574
-			];
575
-		}
576
-		$this->storeResults('core', $result);
577
-
578
-		return $result;
579
-	}
580
-
581
-	/**
582
-	 * Verify the core code of the instance as well as all applicable applications
583
-	 * and store the results.
584
-	 */
585
-	public function runInstanceVerification() {
586
-		$this->cleanResults();
587
-		$this->verifyCoreSignature();
588
-		$appIds = $this->appLocator->getAllApps();
589
-		foreach($appIds as $appId) {
590
-			// If an application is shipped a valid signature is required
591
-			$isShipped = $this->appManager->isShipped($appId);
592
-			$appNeedsToBeChecked = false;
593
-			if ($isShipped) {
594
-				$appNeedsToBeChecked = true;
595
-			} elseif ($this->fileAccessHelper->file_exists($this->appLocator->getAppPath($appId) . '/appinfo/signature.json')) {
596
-				// Otherwise only if the application explicitly ships a signature.json file
597
-				$appNeedsToBeChecked = true;
598
-			}
599
-
600
-			if($appNeedsToBeChecked) {
601
-				$this->verifyAppSignature($appId);
602
-			}
603
-		}
604
-	}
54
+    const CACHE_KEY = 'oc.integritycheck.checker';
55
+    /** @var EnvironmentHelper */
56
+    private $environmentHelper;
57
+    /** @var AppLocator */
58
+    private $appLocator;
59
+    /** @var FileAccessHelper */
60
+    private $fileAccessHelper;
61
+    /** @var IConfig */
62
+    private $config;
63
+    /** @var ICache */
64
+    private $cache;
65
+    /** @var IAppManager */
66
+    private $appManager;
67
+    /** @var ITempManager */
68
+    private $tempManager;
69
+
70
+    /**
71
+     * @param EnvironmentHelper $environmentHelper
72
+     * @param FileAccessHelper $fileAccessHelper
73
+     * @param AppLocator $appLocator
74
+     * @param IConfig $config
75
+     * @param ICacheFactory $cacheFactory
76
+     * @param IAppManager $appManager
77
+     * @param ITempManager $tempManager
78
+     */
79
+    public function __construct(EnvironmentHelper $environmentHelper,
80
+                                FileAccessHelper $fileAccessHelper,
81
+                                AppLocator $appLocator,
82
+                                IConfig $config = null,
83
+                                ICacheFactory $cacheFactory,
84
+                                IAppManager $appManager = null,
85
+                                ITempManager $tempManager) {
86
+        $this->environmentHelper = $environmentHelper;
87
+        $this->fileAccessHelper = $fileAccessHelper;
88
+        $this->appLocator = $appLocator;
89
+        $this->config = $config;
90
+        $this->cache = $cacheFactory->createDistributed(self::CACHE_KEY);
91
+        $this->appManager = $appManager;
92
+        $this->tempManager = $tempManager;
93
+    }
94
+
95
+    /**
96
+     * Whether code signing is enforced or not.
97
+     *
98
+     * @return bool
99
+     */
100
+    public function isCodeCheckEnforced() {
101
+        $notSignedChannels = [ '', 'git'];
102
+        if (in_array($this->environmentHelper->getChannel(), $notSignedChannels, true)) {
103
+            return false;
104
+        }
105
+
106
+        /**
107
+         * This config option is undocumented and supposed to be so, it's only
108
+         * applicable for very specific scenarios and we should not advertise it
109
+         * too prominent. So please do not add it to config.sample.php.
110
+         */
111
+        if ($this->config !== null) {
112
+            $isIntegrityCheckDisabled = $this->config->getSystemValue('integrity.check.disabled', false);
113
+        } else {
114
+            $isIntegrityCheckDisabled = false;
115
+        }
116
+        if ($isIntegrityCheckDisabled === true) {
117
+            return false;
118
+        }
119
+
120
+        return true;
121
+    }
122
+
123
+    /**
124
+     * Enumerates all files belonging to the folder. Sensible defaults are excluded.
125
+     *
126
+     * @param string $folderToIterate
127
+     * @param string $root
128
+     * @return \RecursiveIteratorIterator
129
+     * @throws \Exception
130
+     */
131
+    private function getFolderIterator($folderToIterate, $root = '') {
132
+        $dirItr = new \RecursiveDirectoryIterator(
133
+            $folderToIterate,
134
+            \RecursiveDirectoryIterator::SKIP_DOTS
135
+        );
136
+        if($root === '') {
137
+            $root = \OC::$SERVERROOT;
138
+        }
139
+        $root = rtrim($root, '/');
140
+
141
+        $excludeGenericFilesIterator = new ExcludeFileByNameFilterIterator($dirItr);
142
+        $excludeFoldersIterator = new ExcludeFoldersByPathFilterIterator($excludeGenericFilesIterator, $root);
143
+
144
+        return new \RecursiveIteratorIterator(
145
+            $excludeFoldersIterator,
146
+            \RecursiveIteratorIterator::SELF_FIRST
147
+        );
148
+    }
149
+
150
+    /**
151
+     * Returns an array of ['filename' => 'SHA512-hash-of-file'] for all files found
152
+     * in the iterator.
153
+     *
154
+     * @param \RecursiveIteratorIterator $iterator
155
+     * @param string $path
156
+     * @return array Array of hashes.
157
+     */
158
+    private function generateHashes(\RecursiveIteratorIterator $iterator,
159
+                                    $path) {
160
+        $hashes = [];
161
+        $copiedWebserverSettingFiles = false;
162
+        $tmpFolder = '';
163
+
164
+        $baseDirectoryLength = strlen($path);
165
+        foreach($iterator as $filename => $data) {
166
+            /** @var \DirectoryIterator $data */
167
+            if($data->isDir()) {
168
+                continue;
169
+            }
170
+
171
+            $relativeFileName = substr($filename, $baseDirectoryLength);
172
+            $relativeFileName = ltrim($relativeFileName, '/');
173
+
174
+            // Exclude signature.json files in the appinfo and root folder
175
+            if($relativeFileName === 'appinfo/signature.json') {
176
+                continue;
177
+            }
178
+            // Exclude signature.json files in the appinfo and core folder
179
+            if($relativeFileName === 'core/signature.json') {
180
+                continue;
181
+            }
182
+
183
+            // The .user.ini and the .htaccess file of ownCloud can contain some
184
+            // custom modifications such as for example the maximum upload size
185
+            // to ensure that this will not lead to false positives this will
186
+            // copy the file to a temporary folder and reset it to the default
187
+            // values.
188
+            if($filename === $this->environmentHelper->getServerRoot() . '/.htaccess'
189
+                || $filename === $this->environmentHelper->getServerRoot() . '/.user.ini') {
190
+
191
+                if(!$copiedWebserverSettingFiles) {
192
+                    $tmpFolder = rtrim($this->tempManager->getTemporaryFolder(), '/');
193
+                    copy($this->environmentHelper->getServerRoot() . '/.htaccess', $tmpFolder . '/.htaccess');
194
+                    copy($this->environmentHelper->getServerRoot() . '/.user.ini', $tmpFolder . '/.user.ini');
195
+                    \OC_Files::setUploadLimit(
196
+                        \OCP\Util::computerFileSize('511MB'),
197
+                        [
198
+                            '.htaccess' => $tmpFolder . '/.htaccess',
199
+                            '.user.ini' => $tmpFolder . '/.user.ini',
200
+                        ]
201
+                    );
202
+                }
203
+            }
204
+
205
+            // The .user.ini file can contain custom modifications to the file size
206
+            // as well.
207
+            if($filename === $this->environmentHelper->getServerRoot() . '/.user.ini') {
208
+                $fileContent = file_get_contents($tmpFolder . '/.user.ini');
209
+                $hashes[$relativeFileName] = hash('sha512', $fileContent);
210
+                continue;
211
+            }
212
+
213
+            // The .htaccess file in the root folder of ownCloud can contain
214
+            // custom content after the installation due to the fact that dynamic
215
+            // content is written into it at installation time as well. This
216
+            // includes for example the 404 and 403 instructions.
217
+            // Thus we ignore everything below the first occurrence of
218
+            // "#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####" and have the
219
+            // hash generated based on this.
220
+            if($filename === $this->environmentHelper->getServerRoot() . '/.htaccess') {
221
+                $fileContent = file_get_contents($tmpFolder . '/.htaccess');
222
+                $explodedArray = explode('#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####', $fileContent);
223
+                if(count($explodedArray) === 2) {
224
+                    $hashes[$relativeFileName] = hash('sha512', $explodedArray[0]);
225
+                    continue;
226
+                }
227
+            }
228
+
229
+            $hashes[$relativeFileName] = hash_file('sha512', $filename);
230
+        }
231
+
232
+        return $hashes;
233
+    }
234
+
235
+    /**
236
+     * Creates the signature data
237
+     *
238
+     * @param array $hashes
239
+     * @param X509 $certificate
240
+     * @param RSA $privateKey
241
+     * @return string
242
+     */
243
+    private function createSignatureData(array $hashes,
244
+                                            X509 $certificate,
245
+                                            RSA $privateKey) {
246
+        ksort($hashes);
247
+
248
+        $privateKey->setSignatureMode(RSA::SIGNATURE_PSS);
249
+        $privateKey->setMGFHash('sha512');
250
+        // See https://tools.ietf.org/html/rfc3447#page-38
251
+        $privateKey->setSaltLength(0);
252
+        $signature = $privateKey->sign(json_encode($hashes));
253
+
254
+        return [
255
+                'hashes' => $hashes,
256
+                'signature' => base64_encode($signature),
257
+                'certificate' => $certificate->saveX509($certificate->currentCert),
258
+            ];
259
+    }
260
+
261
+    /**
262
+     * Write the signature of the app in the specified folder
263
+     *
264
+     * @param string $path
265
+     * @param X509 $certificate
266
+     * @param RSA $privateKey
267
+     * @throws \Exception
268
+     */
269
+    public function writeAppSignature($path,
270
+                                        X509 $certificate,
271
+                                        RSA $privateKey) {
272
+        $appInfoDir = $path . '/appinfo';
273
+        try {
274
+            $this->fileAccessHelper->assertDirectoryExists($appInfoDir);
275
+
276
+            $iterator = $this->getFolderIterator($path);
277
+            $hashes = $this->generateHashes($iterator, $path);
278
+            $signature = $this->createSignatureData($hashes, $certificate, $privateKey);
279
+                $this->fileAccessHelper->file_put_contents(
280
+                    $appInfoDir . '/signature.json',
281
+                json_encode($signature, JSON_PRETTY_PRINT)
282
+            );
283
+        } catch (\Exception $e){
284
+            if (!$this->fileAccessHelper->is_writable($appInfoDir)) {
285
+                throw new \Exception($appInfoDir . ' is not writable');
286
+            }
287
+            throw $e;
288
+        }
289
+    }
290
+
291
+    /**
292
+     * Write the signature of core
293
+     *
294
+     * @param X509 $certificate
295
+     * @param RSA $rsa
296
+     * @param string $path
297
+     * @throws \Exception
298
+     */
299
+    public function writeCoreSignature(X509 $certificate,
300
+                                        RSA $rsa,
301
+                                        $path) {
302
+        $coreDir = $path . '/core';
303
+        try {
304
+
305
+            $this->fileAccessHelper->assertDirectoryExists($coreDir);
306
+            $iterator = $this->getFolderIterator($path, $path);
307
+            $hashes = $this->generateHashes($iterator, $path);
308
+            $signatureData = $this->createSignatureData($hashes, $certificate, $rsa);
309
+            $this->fileAccessHelper->file_put_contents(
310
+                $coreDir . '/signature.json',
311
+                json_encode($signatureData, JSON_PRETTY_PRINT)
312
+            );
313
+        } catch (\Exception $e){
314
+            if (!$this->fileAccessHelper->is_writable($coreDir)) {
315
+                throw new \Exception($coreDir . ' is not writable');
316
+            }
317
+            throw $e;
318
+        }
319
+    }
320
+
321
+    /**
322
+     * Verifies the signature for the specified path.
323
+     *
324
+     * @param string $signaturePath
325
+     * @param string $basePath
326
+     * @param string $certificateCN
327
+     * @return array
328
+     * @throws InvalidSignatureException
329
+     * @throws \Exception
330
+     */
331
+    private function verify($signaturePath, $basePath, $certificateCN) {
332
+        if(!$this->isCodeCheckEnforced()) {
333
+            return [];
334
+        }
335
+
336
+        $signatureData = json_decode($this->fileAccessHelper->file_get_contents($signaturePath), true);
337
+        if(!is_array($signatureData)) {
338
+            throw new InvalidSignatureException('Signature data not found.');
339
+        }
340
+
341
+        $expectedHashes = $signatureData['hashes'];
342
+        ksort($expectedHashes);
343
+        $signature = base64_decode($signatureData['signature']);
344
+        $certificate = $signatureData['certificate'];
345
+
346
+        // Check if certificate is signed by Nextcloud Root Authority
347
+        $x509 = new \phpseclib\File\X509();
348
+        $rootCertificatePublicKey = $this->fileAccessHelper->file_get_contents($this->environmentHelper->getServerRoot().'/resources/codesigning/root.crt');
349
+        $x509->loadCA($rootCertificatePublicKey);
350
+        $x509->loadX509($certificate);
351
+        if(!$x509->validateSignature()) {
352
+            throw new InvalidSignatureException('Certificate is not valid.');
353
+        }
354
+        // Verify if certificate has proper CN. "core" CN is always trusted.
355
+        if($x509->getDN(X509::DN_OPENSSL)['CN'] !== $certificateCN && $x509->getDN(X509::DN_OPENSSL)['CN'] !== 'core') {
356
+            throw new InvalidSignatureException(
357
+                    sprintf('Certificate is not valid for required scope. (Requested: %s, current: CN=%s)', $certificateCN, $x509->getDN(true)['CN'])
358
+            );
359
+        }
360
+
361
+        // Check if the signature of the files is valid
362
+        $rsa = new \phpseclib\Crypt\RSA();
363
+        $rsa->loadKey($x509->currentCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']);
364
+        $rsa->setSignatureMode(RSA::SIGNATURE_PSS);
365
+        $rsa->setMGFHash('sha512');
366
+        // See https://tools.ietf.org/html/rfc3447#page-38
367
+        $rsa->setSaltLength(0);
368
+        if(!$rsa->verify(json_encode($expectedHashes), $signature)) {
369
+            throw new InvalidSignatureException('Signature could not get verified.');
370
+        }
371
+
372
+        // Fixes for the updater as shipped with ownCloud 9.0.x: The updater is
373
+        // replaced after the code integrity check is performed.
374
+        //
375
+        // Due to this reason we exclude the whole updater/ folder from the code
376
+        // integrity check.
377
+        if($basePath === $this->environmentHelper->getServerRoot()) {
378
+            foreach($expectedHashes as $fileName => $hash) {
379
+                if(strpos($fileName, 'updater/') === 0) {
380
+                    unset($expectedHashes[$fileName]);
381
+                }
382
+            }
383
+        }
384
+
385
+        // Compare the list of files which are not identical
386
+        $currentInstanceHashes = $this->generateHashes($this->getFolderIterator($basePath), $basePath);
387
+        $differencesA = array_diff($expectedHashes, $currentInstanceHashes);
388
+        $differencesB = array_diff($currentInstanceHashes, $expectedHashes);
389
+        $differences = array_unique(array_merge($differencesA, $differencesB));
390
+        $differenceArray = [];
391
+        foreach($differences as $filename => $hash) {
392
+            // Check if file should not exist in the new signature table
393
+            if(!array_key_exists($filename, $expectedHashes)) {
394
+                $differenceArray['EXTRA_FILE'][$filename]['expected'] = '';
395
+                $differenceArray['EXTRA_FILE'][$filename]['current'] = $hash;
396
+                continue;
397
+            }
398
+
399
+            // Check if file is missing
400
+            if(!array_key_exists($filename, $currentInstanceHashes)) {
401
+                $differenceArray['FILE_MISSING'][$filename]['expected'] = $expectedHashes[$filename];
402
+                $differenceArray['FILE_MISSING'][$filename]['current'] = '';
403
+                continue;
404
+            }
405
+
406
+            // Check if hash does mismatch
407
+            if($expectedHashes[$filename] !== $currentInstanceHashes[$filename]) {
408
+                $differenceArray['INVALID_HASH'][$filename]['expected'] = $expectedHashes[$filename];
409
+                $differenceArray['INVALID_HASH'][$filename]['current'] = $currentInstanceHashes[$filename];
410
+                continue;
411
+            }
412
+
413
+            // Should never happen.
414
+            throw new \Exception('Invalid behaviour in file hash comparison experienced. Please report this error to the developers.');
415
+        }
416
+
417
+        return $differenceArray;
418
+    }
419
+
420
+    /**
421
+     * Whether the code integrity check has passed successful or not
422
+     *
423
+     * @return bool
424
+     */
425
+    public function hasPassedCheck() {
426
+        $results = $this->getResults();
427
+        if(empty($results)) {
428
+            return true;
429
+        }
430
+
431
+        return false;
432
+    }
433
+
434
+    /**
435
+     * @return array
436
+     */
437
+    public function getResults() {
438
+        $cachedResults = $this->cache->get(self::CACHE_KEY);
439
+        if(!is_null($cachedResults)) {
440
+            return json_decode($cachedResults, true);
441
+        }
442
+
443
+        if ($this->config !== null) {
444
+            return json_decode($this->config->getAppValue('core', self::CACHE_KEY, '{}'), true);
445
+        }
446
+        return [];
447
+    }
448
+
449
+    /**
450
+     * Stores the results in the app config as well as cache
451
+     *
452
+     * @param string $scope
453
+     * @param array $result
454
+     */
455
+    private function storeResults($scope, array $result) {
456
+        $resultArray = $this->getResults();
457
+        unset($resultArray[$scope]);
458
+        if(!empty($result)) {
459
+            $resultArray[$scope] = $result;
460
+        }
461
+        if ($this->config !== null) {
462
+            $this->config->setAppValue('core', self::CACHE_KEY, json_encode($resultArray));
463
+        }
464
+        $this->cache->set(self::CACHE_KEY, json_encode($resultArray));
465
+    }
466
+
467
+    /**
468
+     *
469
+     * Clean previous results for a proper rescanning. Otherwise
470
+     */
471
+    private function cleanResults() {
472
+        $this->config->deleteAppValue('core', self::CACHE_KEY);
473
+        $this->cache->remove(self::CACHE_KEY);
474
+    }
475
+
476
+    /**
477
+     * Verify the signature of $appId. Returns an array with the following content:
478
+     * [
479
+     * 	'FILE_MISSING' =>
480
+     * 	[
481
+     * 		'filename' => [
482
+     * 			'expected' => 'expectedSHA512',
483
+     * 			'current' => 'currentSHA512',
484
+     * 		],
485
+     * 	],
486
+     * 	'EXTRA_FILE' =>
487
+     * 	[
488
+     * 		'filename' => [
489
+     * 			'expected' => 'expectedSHA512',
490
+     * 			'current' => 'currentSHA512',
491
+     * 		],
492
+     * 	],
493
+     * 	'INVALID_HASH' =>
494
+     * 	[
495
+     * 		'filename' => [
496
+     * 			'expected' => 'expectedSHA512',
497
+     * 			'current' => 'currentSHA512',
498
+     * 		],
499
+     * 	],
500
+     * ]
501
+     *
502
+     * Array may be empty in case no problems have been found.
503
+     *
504
+     * @param string $appId
505
+     * @param string $path Optional path. If none is given it will be guessed.
506
+     * @return array
507
+     */
508
+    public function verifyAppSignature($appId, $path = '') {
509
+        try {
510
+            if($path === '') {
511
+                $path = $this->appLocator->getAppPath($appId);
512
+            }
513
+            $result = $this->verify(
514
+                    $path . '/appinfo/signature.json',
515
+                    $path,
516
+                    $appId
517
+            );
518
+        } catch (\Exception $e) {
519
+            $result = [
520
+                    'EXCEPTION' => [
521
+                            'class' => get_class($e),
522
+                            'message' => $e->getMessage(),
523
+                    ],
524
+            ];
525
+        }
526
+        $this->storeResults($appId, $result);
527
+
528
+        return $result;
529
+    }
530
+
531
+    /**
532
+     * Verify the signature of core. Returns an array with the following content:
533
+     * [
534
+     * 	'FILE_MISSING' =>
535
+     * 	[
536
+     * 		'filename' => [
537
+     * 			'expected' => 'expectedSHA512',
538
+     * 			'current' => 'currentSHA512',
539
+     * 		],
540
+     * 	],
541
+     * 	'EXTRA_FILE' =>
542
+     * 	[
543
+     * 		'filename' => [
544
+     * 			'expected' => 'expectedSHA512',
545
+     * 			'current' => 'currentSHA512',
546
+     * 		],
547
+     * 	],
548
+     * 	'INVALID_HASH' =>
549
+     * 	[
550
+     * 		'filename' => [
551
+     * 			'expected' => 'expectedSHA512',
552
+     * 			'current' => 'currentSHA512',
553
+     * 		],
554
+     * 	],
555
+     * ]
556
+     *
557
+     * Array may be empty in case no problems have been found.
558
+     *
559
+     * @return array
560
+     */
561
+    public function verifyCoreSignature() {
562
+        try {
563
+            $result = $this->verify(
564
+                    $this->environmentHelper->getServerRoot() . '/core/signature.json',
565
+                    $this->environmentHelper->getServerRoot(),
566
+                    'core'
567
+            );
568
+        } catch (\Exception $e) {
569
+            $result = [
570
+                    'EXCEPTION' => [
571
+                            'class' => get_class($e),
572
+                            'message' => $e->getMessage(),
573
+                    ],
574
+            ];
575
+        }
576
+        $this->storeResults('core', $result);
577
+
578
+        return $result;
579
+    }
580
+
581
+    /**
582
+     * Verify the core code of the instance as well as all applicable applications
583
+     * and store the results.
584
+     */
585
+    public function runInstanceVerification() {
586
+        $this->cleanResults();
587
+        $this->verifyCoreSignature();
588
+        $appIds = $this->appLocator->getAllApps();
589
+        foreach($appIds as $appId) {
590
+            // If an application is shipped a valid signature is required
591
+            $isShipped = $this->appManager->isShipped($appId);
592
+            $appNeedsToBeChecked = false;
593
+            if ($isShipped) {
594
+                $appNeedsToBeChecked = true;
595
+            } elseif ($this->fileAccessHelper->file_exists($this->appLocator->getAppPath($appId) . '/appinfo/signature.json')) {
596
+                // Otherwise only if the application explicitly ships a signature.json file
597
+                $appNeedsToBeChecked = true;
598
+            }
599
+
600
+            if($appNeedsToBeChecked) {
601
+                $this->verifyAppSignature($appId);
602
+            }
603
+        }
604
+    }
605 605
 }
Please login to merge, or discard this patch.