Passed
Push — master ( 62403d...0c3e2f )
by Joas
14:50 queued 14s
created
apps/files_sharing/lib/External/Storage.php 2 patches
Indentation   +378 added lines, -378 removed lines patch added patch discarded remove patch
@@ -45,382 +45,382 @@
 block discarded – undo
45 45
 use OCP\Files\StorageNotAvailableException;
46 46
 
47 47
 class Storage extends DAV implements ISharedStorage, IDisableEncryptionStorage {
48
-	/** @var ICloudId */
49
-	private $cloudId;
50
-	/** @var string */
51
-	private $mountPoint;
52
-	/** @var string */
53
-	private $token;
54
-	/** @var \OCP\ICacheFactory */
55
-	private $memcacheFactory;
56
-	/** @var \OCP\Http\Client\IClientService */
57
-	private $httpClient;
58
-	/** @var bool */
59
-	private $updateChecked = false;
60
-
61
-	/**
62
-	 * @var \OCA\Files_Sharing\External\Manager
63
-	 */
64
-	private $manager;
65
-
66
-	public function __construct($options) {
67
-		$this->memcacheFactory = \OC::$server->getMemCacheFactory();
68
-		$this->httpClient = $options['HttpClientService'];
69
-
70
-		$this->manager = $options['manager'];
71
-		$this->cloudId = $options['cloudId'];
72
-		$discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
73
-
74
-		list($protocol, $remote) = explode('://', $this->cloudId->getRemote());
75
-		if (strpos($remote, '/')) {
76
-			list($host, $root) = explode('/', $remote, 2);
77
-		} else {
78
-			$host = $remote;
79
-			$root = '';
80
-		}
81
-		$secure = $protocol === 'https';
82
-		$federatedSharingEndpoints = $discoveryService->discover($this->cloudId->getRemote(), 'FEDERATED_SHARING');
83
-		$webDavEndpoint = isset($federatedSharingEndpoints['webdav']) ? $federatedSharingEndpoints['webdav'] : '/public.php/webdav';
84
-		$root = rtrim($root, '/') . $webDavEndpoint;
85
-		$this->mountPoint = $options['mountpoint'];
86
-		$this->token = $options['token'];
87
-
88
-		parent::__construct([
89
-			'secure' => $secure,
90
-			'host' => $host,
91
-			'root' => $root,
92
-			'user' => $options['token'],
93
-			'password' => (string)$options['password']
94
-		]);
95
-	}
96
-
97
-	public function getWatcher($path = '', $storage = null) {
98
-		if (!$storage) {
99
-			$storage = $this;
100
-		}
101
-		if (!isset($this->watcher)) {
102
-			$this->watcher = new Watcher($storage);
103
-			$this->watcher->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE);
104
-		}
105
-		return $this->watcher;
106
-	}
107
-
108
-	public function getRemoteUser() {
109
-		return $this->cloudId->getUser();
110
-	}
111
-
112
-	public function getRemote() {
113
-		return $this->cloudId->getRemote();
114
-	}
115
-
116
-	public function getMountPoint() {
117
-		return $this->mountPoint;
118
-	}
119
-
120
-	public function getToken() {
121
-		return $this->token;
122
-	}
123
-
124
-	public function getPassword() {
125
-		return $this->password;
126
-	}
127
-
128
-	/**
129
-	 * @brief get id of the mount point
130
-	 * @return string
131
-	 */
132
-	public function getId() {
133
-		return 'shared::' . md5($this->token . '@' . $this->getRemote());
134
-	}
135
-
136
-	public function getCache($path = '', $storage = null) {
137
-		if (is_null($this->cache)) {
138
-			$this->cache = new Cache($this, $this->cloudId);
139
-		}
140
-		return $this->cache;
141
-	}
142
-
143
-	/**
144
-	 * @param string $path
145
-	 * @param \OC\Files\Storage\Storage $storage
146
-	 * @return \OCA\Files_Sharing\External\Scanner
147
-	 */
148
-	public function getScanner($path = '', $storage = null) {
149
-		if (!$storage) {
150
-			$storage = $this;
151
-		}
152
-		if (!isset($this->scanner)) {
153
-			$this->scanner = new Scanner($storage);
154
-		}
155
-		return $this->scanner;
156
-	}
157
-
158
-	/**
159
-	 * check if a file or folder has been updated since $time
160
-	 *
161
-	 * @param string $path
162
-	 * @param int $time
163
-	 * @throws \OCP\Files\StorageNotAvailableException
164
-	 * @throws \OCP\Files\StorageInvalidException
165
-	 * @return bool
166
-	 */
167
-	public function hasUpdated($path, $time) {
168
-		// since for owncloud webdav servers we can rely on etag propagation we only need to check the root of the storage
169
-		// because of that we only do one check for the entire storage per request
170
-		if ($this->updateChecked) {
171
-			return false;
172
-		}
173
-		$this->updateChecked = true;
174
-		try {
175
-			return parent::hasUpdated('', $time);
176
-		} catch (StorageInvalidException $e) {
177
-			// check if it needs to be removed
178
-			$this->checkStorageAvailability();
179
-			throw $e;
180
-		} catch (StorageNotAvailableException $e) {
181
-			// check if it needs to be removed or just temp unavailable
182
-			$this->checkStorageAvailability();
183
-			throw $e;
184
-		}
185
-	}
186
-
187
-	public function test() {
188
-		try {
189
-			return parent::test();
190
-		} catch (StorageInvalidException $e) {
191
-			// check if it needs to be removed
192
-			$this->checkStorageAvailability();
193
-			throw $e;
194
-		} catch (StorageNotAvailableException $e) {
195
-			// check if it needs to be removed or just temp unavailable
196
-			$this->checkStorageAvailability();
197
-			throw $e;
198
-		}
199
-	}
200
-
201
-	/**
202
-	 * Check whether this storage is permanently or temporarily
203
-	 * unavailable
204
-	 *
205
-	 * @throws \OCP\Files\StorageNotAvailableException
206
-	 * @throws \OCP\Files\StorageInvalidException
207
-	 */
208
-	public function checkStorageAvailability() {
209
-		// see if we can find out why the share is unavailable
210
-		try {
211
-			$this->getShareInfo();
212
-		} catch (NotFoundException $e) {
213
-			// a 404 can either mean that the share no longer exists or there is no Nextcloud on the remote
214
-			if ($this->testRemote()) {
215
-				// valid Nextcloud instance means that the public share no longer exists
216
-				// since this is permanent (re-sharing the file will create a new token)
217
-				// we remove the invalid storage
218
-				$this->manager->removeShare($this->mountPoint);
219
-				$this->manager->getMountManager()->removeMount($this->mountPoint);
220
-				throw new StorageInvalidException();
221
-			} else {
222
-				// Nextcloud instance is gone, likely to be a temporary server configuration error
223
-				throw new StorageNotAvailableException();
224
-			}
225
-		} catch (ForbiddenException $e) {
226
-			// auth error, remove share for now (provide a dialog in the future)
227
-			$this->manager->removeShare($this->mountPoint);
228
-			$this->manager->getMountManager()->removeMount($this->mountPoint);
229
-			throw new StorageInvalidException();
230
-		} catch (\GuzzleHttp\Exception\ConnectException $e) {
231
-			throw new StorageNotAvailableException();
232
-		} catch (\GuzzleHttp\Exception\RequestException $e) {
233
-			throw new StorageNotAvailableException();
234
-		} catch (\Exception $e) {
235
-			throw $e;
236
-		}
237
-	}
238
-
239
-	public function file_exists($path) {
240
-		if ($path === '') {
241
-			return true;
242
-		} else {
243
-			return parent::file_exists($path);
244
-		}
245
-	}
246
-
247
-	/**
248
-	 * check if the configured remote is a valid federated share provider
249
-	 *
250
-	 * @return bool
251
-	 */
252
-	protected function testRemote() {
253
-		try {
254
-			return $this->testRemoteUrl($this->getRemote() . '/ocs-provider/index.php')
255
-				|| $this->testRemoteUrl($this->getRemote() . '/ocs-provider/')
256
-				|| $this->testRemoteUrl($this->getRemote() . '/status.php');
257
-		} catch (\Exception $e) {
258
-			return false;
259
-		}
260
-	}
261
-
262
-	/**
263
-	 * @param string $url
264
-	 * @return bool
265
-	 */
266
-	private function testRemoteUrl($url) {
267
-		$cache = $this->memcacheFactory->createDistributed('files_sharing_remote_url');
268
-		if($cache->hasKey($url)) {
269
-			return (bool)$cache->get($url);
270
-		}
271
-
272
-		$client = $this->httpClient->newClient();
273
-		try {
274
-			$result = $client->get($url, [
275
-				'timeout' => 10,
276
-				'connect_timeout' => 10,
277
-			])->getBody();
278
-			$data = json_decode($result);
279
-			$returnValue = (is_object($data) && !empty($data->version));
280
-		} catch (ConnectException $e) {
281
-			$returnValue = false;
282
-		} catch (ClientException $e) {
283
-			$returnValue = false;
284
-		} catch (RequestException $e) {
285
-			$returnValue = false;
286
-		}
287
-
288
-		$cache->set($url, $returnValue, 60*60*24);
289
-		return $returnValue;
290
-	}
291
-
292
-	/**
293
-	 * Whether the remote is an ownCloud/Nextcloud, used since some sharing features are not
294
-	 * standardized. Let's use this to detect whether to use it.
295
-	 *
296
-	 * @return bool
297
-	 */
298
-	public function remoteIsOwnCloud() {
299
-		if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) {
300
-			return false;
301
-		}
302
-		return true;
303
-	}
304
-
305
-	/**
306
-	 * @return mixed
307
-	 * @throws ForbiddenException
308
-	 * @throws NotFoundException
309
-	 * @throws \Exception
310
-	 */
311
-	public function getShareInfo() {
312
-		$remote = $this->getRemote();
313
-		$token = $this->getToken();
314
-		$password = $this->getPassword();
315
-
316
-		// If remote is not an ownCloud do not try to get any share info
317
-		if(!$this->remoteIsOwnCloud()) {
318
-			return ['status' => 'unsupported'];
319
-		}
320
-
321
-		$url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token;
322
-
323
-		// TODO: DI
324
-		$client = \OC::$server->getHTTPClientService()->newClient();
325
-		try {
326
-			$response = $client->post($url, [
327
-				'body' => ['password' => $password],
328
-				'timeout' => 10,
329
-				'connect_timeout' => 10,
330
-			]);
331
-		} catch (\GuzzleHttp\Exception\RequestException $e) {
332
-			if ($e->getCode() === Http::STATUS_UNAUTHORIZED || $e->getCode() === Http::STATUS_FORBIDDEN) {
333
-				throw new ForbiddenException();
334
-			}
335
-			if ($e->getCode() === Http::STATUS_NOT_FOUND) {
336
-				throw new NotFoundException();
337
-			}
338
-			// throw this to be on the safe side: the share will still be visible
339
-			// in the UI in case the failure is intermittent, and the user will
340
-			// be able to decide whether to remove it if it's really gone
341
-			throw new StorageNotAvailableException();
342
-		}
343
-
344
-		return json_decode($response->getBody(), true);
345
-	}
346
-
347
-	public function getOwner($path) {
348
-		return $this->cloudId->getDisplayId();
349
-	}
350
-
351
-	public function isSharable($path) {
352
-		if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
353
-			return false;
354
-		}
355
-		return ($this->getPermissions($path) & Constants::PERMISSION_SHARE);
356
-	}
357
-
358
-	public function getPermissions($path) {
359
-		$response = $this->propfind($path);
360
-		// old federated sharing permissions
361
-		if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) {
362
-			$permissions = $response['{http://open-collaboration-services.org/ns}share-permissions'];
363
-		} else if (isset($response['{http://open-cloud-mesh.org/ns}share-permissions'])) {
364
-			// permissions provided by the OCM API
365
-			$permissions = $this->ocmPermissions2ncPermissions($response['{http://open-collaboration-services.org/ns}share-permissions']);
366
-		} else {
367
-			// use default permission if remote server doesn't provide the share permissions
368
-			$permissions = $this->getDefaultPermissions($path);
369
-		}
370
-
371
-		return $permissions;
372
-	}
373
-
374
-	public function needsPartFile() {
375
-		return false;
376
-	}
377
-
378
-	/**
379
-	 * translate OCM Permissions to Nextcloud permissions
380
-	 *
381
-	 * @param string $ocmPermissions json encoded OCM permissions
382
-	 * @param string $path path to file
383
-	 * @return int
384
-	 */
385
-	protected function ocmPermissions2ncPermissions($ocmPermissions, $path) {
386
-		try {
387
-			$ocmPermissions = json_decode($ocmPermissions);
388
-			$ncPermissions = 0;
389
-			foreach($ocmPermissions as $permission) {
390
-				switch (strtolower($permission)) {
391
-					case 'read':
392
-						$ncPermissions += Constants::PERMISSION_READ;
393
-						break;
394
-					case 'write':
395
-						$ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
396
-						break;
397
-					case 'share':
398
-						$ncPermissions += Constants::PERMISSION_SHARE;
399
-						break;
400
-					default:
401
-						throw new \Exception();
402
-				}
403
-			}
404
-		} catch (\Exception $e) {
405
-			$ncPermissions = $this->getDefaultPermissions($path);
406
-		}
407
-
408
-		return $ncPermissions;
409
-	}
410
-
411
-	/**
412
-	 * calculate default permissions in case no permissions are provided
413
-	 *
414
-	 * @param $path
415
-	 * @return int
416
-	 */
417
-	protected function getDefaultPermissions($path) {
418
-		if ($this->is_dir($path)) {
419
-			$permissions = Constants::PERMISSION_ALL;
420
-		} else {
421
-			$permissions = Constants::PERMISSION_ALL & ~Constants::PERMISSION_CREATE;
422
-		}
423
-
424
-		return $permissions;
425
-	}
48
+    /** @var ICloudId */
49
+    private $cloudId;
50
+    /** @var string */
51
+    private $mountPoint;
52
+    /** @var string */
53
+    private $token;
54
+    /** @var \OCP\ICacheFactory */
55
+    private $memcacheFactory;
56
+    /** @var \OCP\Http\Client\IClientService */
57
+    private $httpClient;
58
+    /** @var bool */
59
+    private $updateChecked = false;
60
+
61
+    /**
62
+     * @var \OCA\Files_Sharing\External\Manager
63
+     */
64
+    private $manager;
65
+
66
+    public function __construct($options) {
67
+        $this->memcacheFactory = \OC::$server->getMemCacheFactory();
68
+        $this->httpClient = $options['HttpClientService'];
69
+
70
+        $this->manager = $options['manager'];
71
+        $this->cloudId = $options['cloudId'];
72
+        $discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
73
+
74
+        list($protocol, $remote) = explode('://', $this->cloudId->getRemote());
75
+        if (strpos($remote, '/')) {
76
+            list($host, $root) = explode('/', $remote, 2);
77
+        } else {
78
+            $host = $remote;
79
+            $root = '';
80
+        }
81
+        $secure = $protocol === 'https';
82
+        $federatedSharingEndpoints = $discoveryService->discover($this->cloudId->getRemote(), 'FEDERATED_SHARING');
83
+        $webDavEndpoint = isset($federatedSharingEndpoints['webdav']) ? $federatedSharingEndpoints['webdav'] : '/public.php/webdav';
84
+        $root = rtrim($root, '/') . $webDavEndpoint;
85
+        $this->mountPoint = $options['mountpoint'];
86
+        $this->token = $options['token'];
87
+
88
+        parent::__construct([
89
+            'secure' => $secure,
90
+            'host' => $host,
91
+            'root' => $root,
92
+            'user' => $options['token'],
93
+            'password' => (string)$options['password']
94
+        ]);
95
+    }
96
+
97
+    public function getWatcher($path = '', $storage = null) {
98
+        if (!$storage) {
99
+            $storage = $this;
100
+        }
101
+        if (!isset($this->watcher)) {
102
+            $this->watcher = new Watcher($storage);
103
+            $this->watcher->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE);
104
+        }
105
+        return $this->watcher;
106
+    }
107
+
108
+    public function getRemoteUser() {
109
+        return $this->cloudId->getUser();
110
+    }
111
+
112
+    public function getRemote() {
113
+        return $this->cloudId->getRemote();
114
+    }
115
+
116
+    public function getMountPoint() {
117
+        return $this->mountPoint;
118
+    }
119
+
120
+    public function getToken() {
121
+        return $this->token;
122
+    }
123
+
124
+    public function getPassword() {
125
+        return $this->password;
126
+    }
127
+
128
+    /**
129
+     * @brief get id of the mount point
130
+     * @return string
131
+     */
132
+    public function getId() {
133
+        return 'shared::' . md5($this->token . '@' . $this->getRemote());
134
+    }
135
+
136
+    public function getCache($path = '', $storage = null) {
137
+        if (is_null($this->cache)) {
138
+            $this->cache = new Cache($this, $this->cloudId);
139
+        }
140
+        return $this->cache;
141
+    }
142
+
143
+    /**
144
+     * @param string $path
145
+     * @param \OC\Files\Storage\Storage $storage
146
+     * @return \OCA\Files_Sharing\External\Scanner
147
+     */
148
+    public function getScanner($path = '', $storage = null) {
149
+        if (!$storage) {
150
+            $storage = $this;
151
+        }
152
+        if (!isset($this->scanner)) {
153
+            $this->scanner = new Scanner($storage);
154
+        }
155
+        return $this->scanner;
156
+    }
157
+
158
+    /**
159
+     * check if a file or folder has been updated since $time
160
+     *
161
+     * @param string $path
162
+     * @param int $time
163
+     * @throws \OCP\Files\StorageNotAvailableException
164
+     * @throws \OCP\Files\StorageInvalidException
165
+     * @return bool
166
+     */
167
+    public function hasUpdated($path, $time) {
168
+        // since for owncloud webdav servers we can rely on etag propagation we only need to check the root of the storage
169
+        // because of that we only do one check for the entire storage per request
170
+        if ($this->updateChecked) {
171
+            return false;
172
+        }
173
+        $this->updateChecked = true;
174
+        try {
175
+            return parent::hasUpdated('', $time);
176
+        } catch (StorageInvalidException $e) {
177
+            // check if it needs to be removed
178
+            $this->checkStorageAvailability();
179
+            throw $e;
180
+        } catch (StorageNotAvailableException $e) {
181
+            // check if it needs to be removed or just temp unavailable
182
+            $this->checkStorageAvailability();
183
+            throw $e;
184
+        }
185
+    }
186
+
187
+    public function test() {
188
+        try {
189
+            return parent::test();
190
+        } catch (StorageInvalidException $e) {
191
+            // check if it needs to be removed
192
+            $this->checkStorageAvailability();
193
+            throw $e;
194
+        } catch (StorageNotAvailableException $e) {
195
+            // check if it needs to be removed or just temp unavailable
196
+            $this->checkStorageAvailability();
197
+            throw $e;
198
+        }
199
+    }
200
+
201
+    /**
202
+     * Check whether this storage is permanently or temporarily
203
+     * unavailable
204
+     *
205
+     * @throws \OCP\Files\StorageNotAvailableException
206
+     * @throws \OCP\Files\StorageInvalidException
207
+     */
208
+    public function checkStorageAvailability() {
209
+        // see if we can find out why the share is unavailable
210
+        try {
211
+            $this->getShareInfo();
212
+        } catch (NotFoundException $e) {
213
+            // a 404 can either mean that the share no longer exists or there is no Nextcloud on the remote
214
+            if ($this->testRemote()) {
215
+                // valid Nextcloud instance means that the public share no longer exists
216
+                // since this is permanent (re-sharing the file will create a new token)
217
+                // we remove the invalid storage
218
+                $this->manager->removeShare($this->mountPoint);
219
+                $this->manager->getMountManager()->removeMount($this->mountPoint);
220
+                throw new StorageInvalidException();
221
+            } else {
222
+                // Nextcloud instance is gone, likely to be a temporary server configuration error
223
+                throw new StorageNotAvailableException();
224
+            }
225
+        } catch (ForbiddenException $e) {
226
+            // auth error, remove share for now (provide a dialog in the future)
227
+            $this->manager->removeShare($this->mountPoint);
228
+            $this->manager->getMountManager()->removeMount($this->mountPoint);
229
+            throw new StorageInvalidException();
230
+        } catch (\GuzzleHttp\Exception\ConnectException $e) {
231
+            throw new StorageNotAvailableException();
232
+        } catch (\GuzzleHttp\Exception\RequestException $e) {
233
+            throw new StorageNotAvailableException();
234
+        } catch (\Exception $e) {
235
+            throw $e;
236
+        }
237
+    }
238
+
239
+    public function file_exists($path) {
240
+        if ($path === '') {
241
+            return true;
242
+        } else {
243
+            return parent::file_exists($path);
244
+        }
245
+    }
246
+
247
+    /**
248
+     * check if the configured remote is a valid federated share provider
249
+     *
250
+     * @return bool
251
+     */
252
+    protected function testRemote() {
253
+        try {
254
+            return $this->testRemoteUrl($this->getRemote() . '/ocs-provider/index.php')
255
+                || $this->testRemoteUrl($this->getRemote() . '/ocs-provider/')
256
+                || $this->testRemoteUrl($this->getRemote() . '/status.php');
257
+        } catch (\Exception $e) {
258
+            return false;
259
+        }
260
+    }
261
+
262
+    /**
263
+     * @param string $url
264
+     * @return bool
265
+     */
266
+    private function testRemoteUrl($url) {
267
+        $cache = $this->memcacheFactory->createDistributed('files_sharing_remote_url');
268
+        if($cache->hasKey($url)) {
269
+            return (bool)$cache->get($url);
270
+        }
271
+
272
+        $client = $this->httpClient->newClient();
273
+        try {
274
+            $result = $client->get($url, [
275
+                'timeout' => 10,
276
+                'connect_timeout' => 10,
277
+            ])->getBody();
278
+            $data = json_decode($result);
279
+            $returnValue = (is_object($data) && !empty($data->version));
280
+        } catch (ConnectException $e) {
281
+            $returnValue = false;
282
+        } catch (ClientException $e) {
283
+            $returnValue = false;
284
+        } catch (RequestException $e) {
285
+            $returnValue = false;
286
+        }
287
+
288
+        $cache->set($url, $returnValue, 60*60*24);
289
+        return $returnValue;
290
+    }
291
+
292
+    /**
293
+     * Whether the remote is an ownCloud/Nextcloud, used since some sharing features are not
294
+     * standardized. Let's use this to detect whether to use it.
295
+     *
296
+     * @return bool
297
+     */
298
+    public function remoteIsOwnCloud() {
299
+        if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) {
300
+            return false;
301
+        }
302
+        return true;
303
+    }
304
+
305
+    /**
306
+     * @return mixed
307
+     * @throws ForbiddenException
308
+     * @throws NotFoundException
309
+     * @throws \Exception
310
+     */
311
+    public function getShareInfo() {
312
+        $remote = $this->getRemote();
313
+        $token = $this->getToken();
314
+        $password = $this->getPassword();
315
+
316
+        // If remote is not an ownCloud do not try to get any share info
317
+        if(!$this->remoteIsOwnCloud()) {
318
+            return ['status' => 'unsupported'];
319
+        }
320
+
321
+        $url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token;
322
+
323
+        // TODO: DI
324
+        $client = \OC::$server->getHTTPClientService()->newClient();
325
+        try {
326
+            $response = $client->post($url, [
327
+                'body' => ['password' => $password],
328
+                'timeout' => 10,
329
+                'connect_timeout' => 10,
330
+            ]);
331
+        } catch (\GuzzleHttp\Exception\RequestException $e) {
332
+            if ($e->getCode() === Http::STATUS_UNAUTHORIZED || $e->getCode() === Http::STATUS_FORBIDDEN) {
333
+                throw new ForbiddenException();
334
+            }
335
+            if ($e->getCode() === Http::STATUS_NOT_FOUND) {
336
+                throw new NotFoundException();
337
+            }
338
+            // throw this to be on the safe side: the share will still be visible
339
+            // in the UI in case the failure is intermittent, and the user will
340
+            // be able to decide whether to remove it if it's really gone
341
+            throw new StorageNotAvailableException();
342
+        }
343
+
344
+        return json_decode($response->getBody(), true);
345
+    }
346
+
347
+    public function getOwner($path) {
348
+        return $this->cloudId->getDisplayId();
349
+    }
350
+
351
+    public function isSharable($path) {
352
+        if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
353
+            return false;
354
+        }
355
+        return ($this->getPermissions($path) & Constants::PERMISSION_SHARE);
356
+    }
357
+
358
+    public function getPermissions($path) {
359
+        $response = $this->propfind($path);
360
+        // old federated sharing permissions
361
+        if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) {
362
+            $permissions = $response['{http://open-collaboration-services.org/ns}share-permissions'];
363
+        } else if (isset($response['{http://open-cloud-mesh.org/ns}share-permissions'])) {
364
+            // permissions provided by the OCM API
365
+            $permissions = $this->ocmPermissions2ncPermissions($response['{http://open-collaboration-services.org/ns}share-permissions']);
366
+        } else {
367
+            // use default permission if remote server doesn't provide the share permissions
368
+            $permissions = $this->getDefaultPermissions($path);
369
+        }
370
+
371
+        return $permissions;
372
+    }
373
+
374
+    public function needsPartFile() {
375
+        return false;
376
+    }
377
+
378
+    /**
379
+     * translate OCM Permissions to Nextcloud permissions
380
+     *
381
+     * @param string $ocmPermissions json encoded OCM permissions
382
+     * @param string $path path to file
383
+     * @return int
384
+     */
385
+    protected function ocmPermissions2ncPermissions($ocmPermissions, $path) {
386
+        try {
387
+            $ocmPermissions = json_decode($ocmPermissions);
388
+            $ncPermissions = 0;
389
+            foreach($ocmPermissions as $permission) {
390
+                switch (strtolower($permission)) {
391
+                    case 'read':
392
+                        $ncPermissions += Constants::PERMISSION_READ;
393
+                        break;
394
+                    case 'write':
395
+                        $ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
396
+                        break;
397
+                    case 'share':
398
+                        $ncPermissions += Constants::PERMISSION_SHARE;
399
+                        break;
400
+                    default:
401
+                        throw new \Exception();
402
+                }
403
+            }
404
+        } catch (\Exception $e) {
405
+            $ncPermissions = $this->getDefaultPermissions($path);
406
+        }
407
+
408
+        return $ncPermissions;
409
+    }
410
+
411
+    /**
412
+     * calculate default permissions in case no permissions are provided
413
+     *
414
+     * @param $path
415
+     * @return int
416
+     */
417
+    protected function getDefaultPermissions($path) {
418
+        if ($this->is_dir($path)) {
419
+            $permissions = Constants::PERMISSION_ALL;
420
+        } else {
421
+            $permissions = Constants::PERMISSION_ALL & ~Constants::PERMISSION_CREATE;
422
+        }
423
+
424
+        return $permissions;
425
+    }
426 426
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -81,7 +81,7 @@  discard block
 block discarded – undo
81 81
 		$secure = $protocol === 'https';
82 82
 		$federatedSharingEndpoints = $discoveryService->discover($this->cloudId->getRemote(), 'FEDERATED_SHARING');
83 83
 		$webDavEndpoint = isset($federatedSharingEndpoints['webdav']) ? $federatedSharingEndpoints['webdav'] : '/public.php/webdav';
84
-		$root = rtrim($root, '/') . $webDavEndpoint;
84
+		$root = rtrim($root, '/').$webDavEndpoint;
85 85
 		$this->mountPoint = $options['mountpoint'];
86 86
 		$this->token = $options['token'];
87 87
 
@@ -90,7 +90,7 @@  discard block
 block discarded – undo
90 90
 			'host' => $host,
91 91
 			'root' => $root,
92 92
 			'user' => $options['token'],
93
-			'password' => (string)$options['password']
93
+			'password' => (string) $options['password']
94 94
 		]);
95 95
 	}
96 96
 
@@ -130,7 +130,7 @@  discard block
 block discarded – undo
130 130
 	 * @return string
131 131
 	 */
132 132
 	public function getId() {
133
-		return 'shared::' . md5($this->token . '@' . $this->getRemote());
133
+		return 'shared::'.md5($this->token.'@'.$this->getRemote());
134 134
 	}
135 135
 
136 136
 	public function getCache($path = '', $storage = null) {
@@ -251,9 +251,9 @@  discard block
 block discarded – undo
251 251
 	 */
252 252
 	protected function testRemote() {
253 253
 		try {
254
-			return $this->testRemoteUrl($this->getRemote() . '/ocs-provider/index.php')
255
-				|| $this->testRemoteUrl($this->getRemote() . '/ocs-provider/')
256
-				|| $this->testRemoteUrl($this->getRemote() . '/status.php');
254
+			return $this->testRemoteUrl($this->getRemote().'/ocs-provider/index.php')
255
+				|| $this->testRemoteUrl($this->getRemote().'/ocs-provider/')
256
+				|| $this->testRemoteUrl($this->getRemote().'/status.php');
257 257
 		} catch (\Exception $e) {
258 258
 			return false;
259 259
 		}
@@ -265,8 +265,8 @@  discard block
 block discarded – undo
265 265
 	 */
266 266
 	private function testRemoteUrl($url) {
267 267
 		$cache = $this->memcacheFactory->createDistributed('files_sharing_remote_url');
268
-		if($cache->hasKey($url)) {
269
-			return (bool)$cache->get($url);
268
+		if ($cache->hasKey($url)) {
269
+			return (bool) $cache->get($url);
270 270
 		}
271 271
 
272 272
 		$client = $this->httpClient->newClient();
@@ -285,7 +285,7 @@  discard block
 block discarded – undo
285 285
 			$returnValue = false;
286 286
 		}
287 287
 
288
-		$cache->set($url, $returnValue, 60*60*24);
288
+		$cache->set($url, $returnValue, 60 * 60 * 24);
289 289
 		return $returnValue;
290 290
 	}
291 291
 
@@ -296,7 +296,7 @@  discard block
 block discarded – undo
296 296
 	 * @return bool
297 297
 	 */
298 298
 	public function remoteIsOwnCloud() {
299
-		if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) {
299
+		if (defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote().'/status.php')) {
300 300
 			return false;
301 301
 		}
302 302
 		return true;
@@ -314,11 +314,11 @@  discard block
 block discarded – undo
314 314
 		$password = $this->getPassword();
315 315
 
316 316
 		// If remote is not an ownCloud do not try to get any share info
317
-		if(!$this->remoteIsOwnCloud()) {
317
+		if (!$this->remoteIsOwnCloud()) {
318 318
 			return ['status' => 'unsupported'];
319 319
 		}
320 320
 
321
-		$url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token;
321
+		$url = rtrim($remote, '/').'/index.php/apps/files_sharing/shareinfo?t='.$token;
322 322
 
323 323
 		// TODO: DI
324 324
 		$client = \OC::$server->getHTTPClientService()->newClient();
@@ -386,7 +386,7 @@  discard block
 block discarded – undo
386 386
 		try {
387 387
 			$ocmPermissions = json_decode($ocmPermissions);
388 388
 			$ncPermissions = 0;
389
-			foreach($ocmPermissions as $permission) {
389
+			foreach ($ocmPermissions as $permission) {
390 390
 				switch (strtolower($permission)) {
391 391
 					case 'read':
392 392
 						$ncPermissions += Constants::PERMISSION_READ;
Please login to merge, or discard this patch.
apps/files_sharing/lib/SharedStorage.php 2 patches
Indentation   +455 added lines, -455 removed lines patch added patch discarded remove patch
@@ -49,459 +49,459 @@
 block discarded – undo
49 49
  */
50 50
 class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage, IDisableEncryptionStorage {
51 51
 
52
-	/** @var \OCP\Share\IShare */
53
-	private $superShare;
54
-
55
-	/** @var \OCP\Share\IShare[] */
56
-	private $groupedShares;
57
-
58
-	/**
59
-	 * @var \OC\Files\View
60
-	 */
61
-	private $ownerView;
62
-
63
-	private $initialized = false;
64
-
65
-	/**
66
-	 * @var ICacheEntry
67
-	 */
68
-	private $sourceRootInfo;
69
-
70
-	/** @var string */
71
-	private $user;
72
-
73
-	/**
74
-	 * @var \OCP\ILogger
75
-	 */
76
-	private $logger;
77
-
78
-	/** @var  IStorage */
79
-	private $nonMaskedStorage;
80
-
81
-	private $options;
82
-
83
-	/** @var boolean */
84
-	private $sharingDisabledForUser;
85
-
86
-	public function __construct($arguments) {
87
-		$this->ownerView = $arguments['ownerView'];
88
-		$this->logger = \OC::$server->getLogger();
89
-
90
-		$this->superShare = $arguments['superShare'];
91
-		$this->groupedShares = $arguments['groupedShares'];
92
-
93
-		$this->user = $arguments['user'];
94
-		if (isset($arguments['sharingDisabledForUser'])) {
95
-			$this->sharingDisabledForUser = $arguments['sharingDisabledForUser'];
96
-		} else {
97
-			$this->sharingDisabledForUser = false;
98
-		}
99
-
100
-		parent::__construct([
101
-			'storage' => null,
102
-			'root' => null,
103
-		]);
104
-	}
105
-
106
-	/**
107
-	 * @return ICacheEntry
108
-	 */
109
-	private function getSourceRootInfo() {
110
-		if (is_null($this->sourceRootInfo)) {
111
-			if (is_null($this->superShare->getNodeCacheEntry())) {
112
-				$this->init();
113
-				$this->sourceRootInfo = $this->nonMaskedStorage->getCache()->get($this->rootPath);
114
-			} else {
115
-				$this->sourceRootInfo = $this->superShare->getNodeCacheEntry();
116
-			}
117
-		}
118
-		return $this->sourceRootInfo;
119
-	}
120
-
121
-	private function init() {
122
-		if ($this->initialized) {
123
-			return;
124
-		}
125
-		$this->initialized = true;
126
-		try {
127
-			Filesystem::initMountPoints($this->superShare->getShareOwner());
128
-			$sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
129
-			list($this->nonMaskedStorage, $this->rootPath) = $this->ownerView->resolvePath($sourcePath);
130
-			$this->storage = new PermissionsMask([
131
-				'storage' => $this->nonMaskedStorage,
132
-				'mask' => $this->superShare->getPermissions()
133
-			]);
134
-		} catch (NotFoundException $e) {
135
-			// original file not accessible or deleted, set FailedStorage
136
-			$this->storage = new FailedStorage(['exception' => $e]);
137
-			$this->cache = new FailedCache();
138
-			$this->rootPath = '';
139
-		} catch (NoUserException $e) {
140
-			// sharer user deleted, set FailedStorage
141
-			$this->storage = new FailedStorage(['exception' => $e]);
142
-			$this->cache = new FailedCache();
143
-			$this->rootPath = '';
144
-		} catch (\Exception $e) {
145
-			$this->storage = new FailedStorage(['exception' => $e]);
146
-			$this->cache = new FailedCache();
147
-			$this->rootPath = '';
148
-			$this->logger->logException($e);
149
-		}
150
-
151
-		if (!$this->nonMaskedStorage) {
152
-			$this->nonMaskedStorage = $this->storage;
153
-		}
154
-	}
155
-
156
-	/**
157
-	 * @inheritdoc
158
-	 */
159
-	public function instanceOfStorage($class) {
160
-		if ($class === '\OC\Files\Storage\Common') {
161
-			return true;
162
-		}
163
-		if (in_array($class, ['\OC\Files\Storage\Home', '\OC\Files\ObjectStore\HomeObjectStoreStorage'])) {
164
-			return false;
165
-		}
166
-		return parent::instanceOfStorage($class);
167
-	}
168
-
169
-	/**
170
-	 * @return string
171
-	 */
172
-	public function getShareId() {
173
-		return $this->superShare->getId();
174
-	}
175
-
176
-	private function isValid() {
177
-		return $this->getSourceRootInfo() && ($this->getSourceRootInfo()->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE;
178
-	}
179
-
180
-	/**
181
-	 * get id of the mount point
182
-	 *
183
-	 * @return string
184
-	 */
185
-	public function getId() {
186
-		return 'shared::' . $this->getMountPoint();
187
-	}
188
-
189
-	/**
190
-	 * Get the permissions granted for a shared file
191
-	 *
192
-	 * @param string $target Shared target file path
193
-	 * @return int CRUDS permissions granted
194
-	 */
195
-	public function getPermissions($target = '') {
196
-		if (!$this->isValid()) {
197
-			return 0;
198
-		}
199
-		$permissions = parent::getPermissions($target) & $this->superShare->getPermissions();
200
-
201
-		// part files and the mount point always have delete permissions
202
-		if ($target === '' || pathinfo($target, PATHINFO_EXTENSION) === 'part') {
203
-			$permissions |= \OCP\Constants::PERMISSION_DELETE;
204
-		}
205
-
206
-		if ($this->sharingDisabledForUser) {
207
-			$permissions &= ~\OCP\Constants::PERMISSION_SHARE;
208
-		}
209
-
210
-		return $permissions;
211
-	}
212
-
213
-	public function isCreatable($path) {
214
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_CREATE);
215
-	}
216
-
217
-	public function isReadable($path) {
218
-		if (!$this->isValid()) {
219
-			return false;
220
-		}
221
-		if (!$this->file_exists($path)) {
222
-			return false;
223
-		}
224
-		/** @var IStorage $storage */
225
-		/** @var string $internalPath */
226
-		list($storage, $internalPath) = $this->resolvePath($path);
227
-		return $storage->isReadable($internalPath);
228
-	}
229
-
230
-	public function isUpdatable($path) {
231
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_UPDATE);
232
-	}
233
-
234
-	public function isDeletable($path) {
235
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_DELETE);
236
-	}
237
-
238
-	public function isSharable($path) {
239
-		if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
240
-			return false;
241
-		}
242
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_SHARE);
243
-	}
244
-
245
-	public function fopen($path, $mode) {
246
-		if ($source = $this->getUnjailedPath($path)) {
247
-			switch ($mode) {
248
-				case 'r+':
249
-				case 'rb+':
250
-				case 'w+':
251
-				case 'wb+':
252
-				case 'x+':
253
-				case 'xb+':
254
-				case 'a+':
255
-				case 'ab+':
256
-				case 'w':
257
-				case 'wb':
258
-				case 'x':
259
-				case 'xb':
260
-				case 'a':
261
-				case 'ab':
262
-					$creatable = $this->isCreatable(dirname($path));
263
-					$updatable = $this->isUpdatable($path);
264
-					// if neither permissions given, no need to continue
265
-					if (!$creatable && !$updatable) {
266
-						if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
267
-							$updatable = $this->isUpdatable(dirname($path));
268
-						}
269
-
270
-						if (!$updatable) {
271
-							return false;
272
-						}
273
-					}
274
-
275
-					$exists = $this->file_exists($path);
276
-					// if a file exists, updatable permissions are required
277
-					if ($exists && !$updatable) {
278
-						return false;
279
-					}
280
-
281
-					// part file is allowed if !$creatable but the final file is $updatable
282
-					if (pathinfo($path, PATHINFO_EXTENSION) !== 'part') {
283
-						if (!$exists && !$creatable) {
284
-							return false;
285
-						}
286
-					}
287
-			}
288
-			$info = [
289
-				'target' => $this->getMountPoint() . $path,
290
-				'source' => $source,
291
-				'mode' => $mode,
292
-			];
293
-			\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info);
294
-			return $this->nonMaskedStorage->fopen($this->getUnjailedPath($path), $mode);
295
-		}
296
-		return false;
297
-	}
298
-
299
-	/**
300
-	 * see http://php.net/manual/en/function.rename.php
301
-	 *
302
-	 * @param string $path1
303
-	 * @param string $path2
304
-	 * @return bool
305
-	 */
306
-	public function rename($path1, $path2) {
307
-		$this->init();
308
-		$isPartFile = pathinfo($path1, PATHINFO_EXTENSION) === 'part';
309
-		$targetExists = $this->file_exists($path2);
310
-		$sameFodler = dirname($path1) === dirname($path2);
311
-
312
-		if ($targetExists || ($sameFodler && !$isPartFile)) {
313
-			if (!$this->isUpdatable('')) {
314
-				return false;
315
-			}
316
-		} else {
317
-			if (!$this->isCreatable('')) {
318
-				return false;
319
-			}
320
-		}
321
-
322
-		return $this->nonMaskedStorage->rename($this->getUnjailedPath($path1), $this->getUnjailedPath($path2));
323
-	}
324
-
325
-	/**
326
-	 * return mount point of share, relative to data/user/files
327
-	 *
328
-	 * @return string
329
-	 */
330
-	public function getMountPoint() {
331
-		return $this->superShare->getTarget();
332
-	}
333
-
334
-	/**
335
-	 * @param string $path
336
-	 */
337
-	public function setMountPoint($path) {
338
-		$this->superShare->setTarget($path);
339
-
340
-		foreach ($this->groupedShares as $share) {
341
-			$share->setTarget($path);
342
-		}
343
-	}
344
-
345
-	/**
346
-	 * get the user who shared the file
347
-	 *
348
-	 * @return string
349
-	 */
350
-	public function getSharedFrom() {
351
-		return $this->superShare->getShareOwner();
352
-	}
353
-
354
-	/**
355
-	 * @return \OCP\Share\IShare
356
-	 */
357
-	public function getShare() {
358
-		return $this->superShare;
359
-	}
360
-
361
-	/**
362
-	 * return share type, can be "file" or "folder"
363
-	 *
364
-	 * @return string
365
-	 */
366
-	public function getItemType() {
367
-		return $this->superShare->getNodeType();
368
-	}
369
-
370
-	/**
371
-	 * @param string $path
372
-	 * @param null $storage
373
-	 * @return Cache
374
-	 */
375
-	public function getCache($path = '', $storage = null) {
376
-		if ($this->cache) {
377
-			return $this->cache;
378
-		}
379
-		if (!$storage) {
380
-			$storage = $this;
381
-		}
382
-		$sourceRoot  = $this->getSourceRootInfo();
383
-		if ($this->storage instanceof FailedStorage) {
384
-			return new FailedCache();
385
-		}
386
-
387
-		$this->cache = new \OCA\Files_Sharing\Cache($storage, $sourceRoot, $this->superShare);
388
-		return $this->cache;
389
-	}
390
-
391
-	public function getScanner($path = '', $storage = null) {
392
-		if (!$storage) {
393
-			$storage = $this;
394
-		}
395
-		return new \OCA\Files_Sharing\Scanner($storage);
396
-	}
397
-
398
-	public function getOwner($path) {
399
-		return $this->superShare->getShareOwner();
400
-	}
401
-
402
-	/**
403
-	 * unshare complete storage, also the grouped shares
404
-	 *
405
-	 * @return bool
406
-	 */
407
-	public function unshareStorage() {
408
-		foreach ($this->groupedShares as $share) {
409
-			\OC::$server->getShareManager()->deleteFromSelf($share, $this->user);
410
-		}
411
-		return true;
412
-	}
413
-
414
-	/**
415
-	 * @param string $path
416
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
417
-	 * @param \OCP\Lock\ILockingProvider $provider
418
-	 * @throws \OCP\Lock\LockedException
419
-	 */
420
-	public function acquireLock($path, $type, ILockingProvider $provider) {
421
-		/** @var \OCP\Files\Storage $targetStorage */
422
-		list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
423
-		$targetStorage->acquireLock($targetInternalPath, $type, $provider);
424
-		// lock the parent folders of the owner when locking the share as recipient
425
-		if ($path === '') {
426
-			$sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
427
-			$this->ownerView->lockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
428
-		}
429
-	}
430
-
431
-	/**
432
-	 * @param string $path
433
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
434
-	 * @param \OCP\Lock\ILockingProvider $provider
435
-	 */
436
-	public function releaseLock($path, $type, ILockingProvider $provider) {
437
-		/** @var \OCP\Files\Storage $targetStorage */
438
-		list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
439
-		$targetStorage->releaseLock($targetInternalPath, $type, $provider);
440
-		// unlock the parent folders of the owner when unlocking the share as recipient
441
-		if ($path === '') {
442
-			$sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
443
-			$this->ownerView->unlockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
444
-		}
445
-	}
446
-
447
-	/**
448
-	 * @param string $path
449
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
450
-	 * @param \OCP\Lock\ILockingProvider $provider
451
-	 */
452
-	public function changeLock($path, $type, ILockingProvider $provider) {
453
-		/** @var \OCP\Files\Storage $targetStorage */
454
-		list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
455
-		$targetStorage->changeLock($targetInternalPath, $type, $provider);
456
-	}
457
-
458
-	/**
459
-	 * @return array [ available, last_checked ]
460
-	 */
461
-	public function getAvailability() {
462
-		// shares do not participate in availability logic
463
-		return [
464
-			'available' => true,
465
-			'last_checked' => 0
466
-		];
467
-	}
468
-
469
-	/**
470
-	 * @param bool $available
471
-	 */
472
-	public function setAvailability($available) {
473
-		// shares do not participate in availability logic
474
-	}
475
-
476
-	public function getSourceStorage() {
477
-		$this->init();
478
-		return $this->nonMaskedStorage;
479
-	}
480
-
481
-	public function getWrapperStorage() {
482
-		$this->init();
483
-		return $this->storage;
484
-	}
485
-
486
-	public function file_get_contents($path) {
487
-		$info = [
488
-			'target' => $this->getMountPoint() . '/' . $path,
489
-			'source' => $this->getUnjailedPath($path),
490
-		];
491
-		\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info);
492
-		return parent::file_get_contents($path);
493
-	}
494
-
495
-	public function file_put_contents($path, $data) {
496
-		$info = [
497
-			'target' => $this->getMountPoint() . '/' . $path,
498
-			'source' => $this->getUnjailedPath($path),
499
-		];
500
-		\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info);
501
-		return parent::file_put_contents($path, $data);
502
-	}
503
-
504
-	public function setMountOptions(array $options) {
505
-		$this->mountOptions = $options;
506
-	}
52
+    /** @var \OCP\Share\IShare */
53
+    private $superShare;
54
+
55
+    /** @var \OCP\Share\IShare[] */
56
+    private $groupedShares;
57
+
58
+    /**
59
+     * @var \OC\Files\View
60
+     */
61
+    private $ownerView;
62
+
63
+    private $initialized = false;
64
+
65
+    /**
66
+     * @var ICacheEntry
67
+     */
68
+    private $sourceRootInfo;
69
+
70
+    /** @var string */
71
+    private $user;
72
+
73
+    /**
74
+     * @var \OCP\ILogger
75
+     */
76
+    private $logger;
77
+
78
+    /** @var  IStorage */
79
+    private $nonMaskedStorage;
80
+
81
+    private $options;
82
+
83
+    /** @var boolean */
84
+    private $sharingDisabledForUser;
85
+
86
+    public function __construct($arguments) {
87
+        $this->ownerView = $arguments['ownerView'];
88
+        $this->logger = \OC::$server->getLogger();
89
+
90
+        $this->superShare = $arguments['superShare'];
91
+        $this->groupedShares = $arguments['groupedShares'];
92
+
93
+        $this->user = $arguments['user'];
94
+        if (isset($arguments['sharingDisabledForUser'])) {
95
+            $this->sharingDisabledForUser = $arguments['sharingDisabledForUser'];
96
+        } else {
97
+            $this->sharingDisabledForUser = false;
98
+        }
99
+
100
+        parent::__construct([
101
+            'storage' => null,
102
+            'root' => null,
103
+        ]);
104
+    }
105
+
106
+    /**
107
+     * @return ICacheEntry
108
+     */
109
+    private function getSourceRootInfo() {
110
+        if (is_null($this->sourceRootInfo)) {
111
+            if (is_null($this->superShare->getNodeCacheEntry())) {
112
+                $this->init();
113
+                $this->sourceRootInfo = $this->nonMaskedStorage->getCache()->get($this->rootPath);
114
+            } else {
115
+                $this->sourceRootInfo = $this->superShare->getNodeCacheEntry();
116
+            }
117
+        }
118
+        return $this->sourceRootInfo;
119
+    }
120
+
121
+    private function init() {
122
+        if ($this->initialized) {
123
+            return;
124
+        }
125
+        $this->initialized = true;
126
+        try {
127
+            Filesystem::initMountPoints($this->superShare->getShareOwner());
128
+            $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
129
+            list($this->nonMaskedStorage, $this->rootPath) = $this->ownerView->resolvePath($sourcePath);
130
+            $this->storage = new PermissionsMask([
131
+                'storage' => $this->nonMaskedStorage,
132
+                'mask' => $this->superShare->getPermissions()
133
+            ]);
134
+        } catch (NotFoundException $e) {
135
+            // original file not accessible or deleted, set FailedStorage
136
+            $this->storage = new FailedStorage(['exception' => $e]);
137
+            $this->cache = new FailedCache();
138
+            $this->rootPath = '';
139
+        } catch (NoUserException $e) {
140
+            // sharer user deleted, set FailedStorage
141
+            $this->storage = new FailedStorage(['exception' => $e]);
142
+            $this->cache = new FailedCache();
143
+            $this->rootPath = '';
144
+        } catch (\Exception $e) {
145
+            $this->storage = new FailedStorage(['exception' => $e]);
146
+            $this->cache = new FailedCache();
147
+            $this->rootPath = '';
148
+            $this->logger->logException($e);
149
+        }
150
+
151
+        if (!$this->nonMaskedStorage) {
152
+            $this->nonMaskedStorage = $this->storage;
153
+        }
154
+    }
155
+
156
+    /**
157
+     * @inheritdoc
158
+     */
159
+    public function instanceOfStorage($class) {
160
+        if ($class === '\OC\Files\Storage\Common') {
161
+            return true;
162
+        }
163
+        if (in_array($class, ['\OC\Files\Storage\Home', '\OC\Files\ObjectStore\HomeObjectStoreStorage'])) {
164
+            return false;
165
+        }
166
+        return parent::instanceOfStorage($class);
167
+    }
168
+
169
+    /**
170
+     * @return string
171
+     */
172
+    public function getShareId() {
173
+        return $this->superShare->getId();
174
+    }
175
+
176
+    private function isValid() {
177
+        return $this->getSourceRootInfo() && ($this->getSourceRootInfo()->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE;
178
+    }
179
+
180
+    /**
181
+     * get id of the mount point
182
+     *
183
+     * @return string
184
+     */
185
+    public function getId() {
186
+        return 'shared::' . $this->getMountPoint();
187
+    }
188
+
189
+    /**
190
+     * Get the permissions granted for a shared file
191
+     *
192
+     * @param string $target Shared target file path
193
+     * @return int CRUDS permissions granted
194
+     */
195
+    public function getPermissions($target = '') {
196
+        if (!$this->isValid()) {
197
+            return 0;
198
+        }
199
+        $permissions = parent::getPermissions($target) & $this->superShare->getPermissions();
200
+
201
+        // part files and the mount point always have delete permissions
202
+        if ($target === '' || pathinfo($target, PATHINFO_EXTENSION) === 'part') {
203
+            $permissions |= \OCP\Constants::PERMISSION_DELETE;
204
+        }
205
+
206
+        if ($this->sharingDisabledForUser) {
207
+            $permissions &= ~\OCP\Constants::PERMISSION_SHARE;
208
+        }
209
+
210
+        return $permissions;
211
+    }
212
+
213
+    public function isCreatable($path) {
214
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_CREATE);
215
+    }
216
+
217
+    public function isReadable($path) {
218
+        if (!$this->isValid()) {
219
+            return false;
220
+        }
221
+        if (!$this->file_exists($path)) {
222
+            return false;
223
+        }
224
+        /** @var IStorage $storage */
225
+        /** @var string $internalPath */
226
+        list($storage, $internalPath) = $this->resolvePath($path);
227
+        return $storage->isReadable($internalPath);
228
+    }
229
+
230
+    public function isUpdatable($path) {
231
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_UPDATE);
232
+    }
233
+
234
+    public function isDeletable($path) {
235
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_DELETE);
236
+    }
237
+
238
+    public function isSharable($path) {
239
+        if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
240
+            return false;
241
+        }
242
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_SHARE);
243
+    }
244
+
245
+    public function fopen($path, $mode) {
246
+        if ($source = $this->getUnjailedPath($path)) {
247
+            switch ($mode) {
248
+                case 'r+':
249
+                case 'rb+':
250
+                case 'w+':
251
+                case 'wb+':
252
+                case 'x+':
253
+                case 'xb+':
254
+                case 'a+':
255
+                case 'ab+':
256
+                case 'w':
257
+                case 'wb':
258
+                case 'x':
259
+                case 'xb':
260
+                case 'a':
261
+                case 'ab':
262
+                    $creatable = $this->isCreatable(dirname($path));
263
+                    $updatable = $this->isUpdatable($path);
264
+                    // if neither permissions given, no need to continue
265
+                    if (!$creatable && !$updatable) {
266
+                        if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
267
+                            $updatable = $this->isUpdatable(dirname($path));
268
+                        }
269
+
270
+                        if (!$updatable) {
271
+                            return false;
272
+                        }
273
+                    }
274
+
275
+                    $exists = $this->file_exists($path);
276
+                    // if a file exists, updatable permissions are required
277
+                    if ($exists && !$updatable) {
278
+                        return false;
279
+                    }
280
+
281
+                    // part file is allowed if !$creatable but the final file is $updatable
282
+                    if (pathinfo($path, PATHINFO_EXTENSION) !== 'part') {
283
+                        if (!$exists && !$creatable) {
284
+                            return false;
285
+                        }
286
+                    }
287
+            }
288
+            $info = [
289
+                'target' => $this->getMountPoint() . $path,
290
+                'source' => $source,
291
+                'mode' => $mode,
292
+            ];
293
+            \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info);
294
+            return $this->nonMaskedStorage->fopen($this->getUnjailedPath($path), $mode);
295
+        }
296
+        return false;
297
+    }
298
+
299
+    /**
300
+     * see http://php.net/manual/en/function.rename.php
301
+     *
302
+     * @param string $path1
303
+     * @param string $path2
304
+     * @return bool
305
+     */
306
+    public function rename($path1, $path2) {
307
+        $this->init();
308
+        $isPartFile = pathinfo($path1, PATHINFO_EXTENSION) === 'part';
309
+        $targetExists = $this->file_exists($path2);
310
+        $sameFodler = dirname($path1) === dirname($path2);
311
+
312
+        if ($targetExists || ($sameFodler && !$isPartFile)) {
313
+            if (!$this->isUpdatable('')) {
314
+                return false;
315
+            }
316
+        } else {
317
+            if (!$this->isCreatable('')) {
318
+                return false;
319
+            }
320
+        }
321
+
322
+        return $this->nonMaskedStorage->rename($this->getUnjailedPath($path1), $this->getUnjailedPath($path2));
323
+    }
324
+
325
+    /**
326
+     * return mount point of share, relative to data/user/files
327
+     *
328
+     * @return string
329
+     */
330
+    public function getMountPoint() {
331
+        return $this->superShare->getTarget();
332
+    }
333
+
334
+    /**
335
+     * @param string $path
336
+     */
337
+    public function setMountPoint($path) {
338
+        $this->superShare->setTarget($path);
339
+
340
+        foreach ($this->groupedShares as $share) {
341
+            $share->setTarget($path);
342
+        }
343
+    }
344
+
345
+    /**
346
+     * get the user who shared the file
347
+     *
348
+     * @return string
349
+     */
350
+    public function getSharedFrom() {
351
+        return $this->superShare->getShareOwner();
352
+    }
353
+
354
+    /**
355
+     * @return \OCP\Share\IShare
356
+     */
357
+    public function getShare() {
358
+        return $this->superShare;
359
+    }
360
+
361
+    /**
362
+     * return share type, can be "file" or "folder"
363
+     *
364
+     * @return string
365
+     */
366
+    public function getItemType() {
367
+        return $this->superShare->getNodeType();
368
+    }
369
+
370
+    /**
371
+     * @param string $path
372
+     * @param null $storage
373
+     * @return Cache
374
+     */
375
+    public function getCache($path = '', $storage = null) {
376
+        if ($this->cache) {
377
+            return $this->cache;
378
+        }
379
+        if (!$storage) {
380
+            $storage = $this;
381
+        }
382
+        $sourceRoot  = $this->getSourceRootInfo();
383
+        if ($this->storage instanceof FailedStorage) {
384
+            return new FailedCache();
385
+        }
386
+
387
+        $this->cache = new \OCA\Files_Sharing\Cache($storage, $sourceRoot, $this->superShare);
388
+        return $this->cache;
389
+    }
390
+
391
+    public function getScanner($path = '', $storage = null) {
392
+        if (!$storage) {
393
+            $storage = $this;
394
+        }
395
+        return new \OCA\Files_Sharing\Scanner($storage);
396
+    }
397
+
398
+    public function getOwner($path) {
399
+        return $this->superShare->getShareOwner();
400
+    }
401
+
402
+    /**
403
+     * unshare complete storage, also the grouped shares
404
+     *
405
+     * @return bool
406
+     */
407
+    public function unshareStorage() {
408
+        foreach ($this->groupedShares as $share) {
409
+            \OC::$server->getShareManager()->deleteFromSelf($share, $this->user);
410
+        }
411
+        return true;
412
+    }
413
+
414
+    /**
415
+     * @param string $path
416
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
417
+     * @param \OCP\Lock\ILockingProvider $provider
418
+     * @throws \OCP\Lock\LockedException
419
+     */
420
+    public function acquireLock($path, $type, ILockingProvider $provider) {
421
+        /** @var \OCP\Files\Storage $targetStorage */
422
+        list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
423
+        $targetStorage->acquireLock($targetInternalPath, $type, $provider);
424
+        // lock the parent folders of the owner when locking the share as recipient
425
+        if ($path === '') {
426
+            $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
427
+            $this->ownerView->lockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
428
+        }
429
+    }
430
+
431
+    /**
432
+     * @param string $path
433
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
434
+     * @param \OCP\Lock\ILockingProvider $provider
435
+     */
436
+    public function releaseLock($path, $type, ILockingProvider $provider) {
437
+        /** @var \OCP\Files\Storage $targetStorage */
438
+        list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
439
+        $targetStorage->releaseLock($targetInternalPath, $type, $provider);
440
+        // unlock the parent folders of the owner when unlocking the share as recipient
441
+        if ($path === '') {
442
+            $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
443
+            $this->ownerView->unlockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
444
+        }
445
+    }
446
+
447
+    /**
448
+     * @param string $path
449
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
450
+     * @param \OCP\Lock\ILockingProvider $provider
451
+     */
452
+    public function changeLock($path, $type, ILockingProvider $provider) {
453
+        /** @var \OCP\Files\Storage $targetStorage */
454
+        list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
455
+        $targetStorage->changeLock($targetInternalPath, $type, $provider);
456
+    }
457
+
458
+    /**
459
+     * @return array [ available, last_checked ]
460
+     */
461
+    public function getAvailability() {
462
+        // shares do not participate in availability logic
463
+        return [
464
+            'available' => true,
465
+            'last_checked' => 0
466
+        ];
467
+    }
468
+
469
+    /**
470
+     * @param bool $available
471
+     */
472
+    public function setAvailability($available) {
473
+        // shares do not participate in availability logic
474
+    }
475
+
476
+    public function getSourceStorage() {
477
+        $this->init();
478
+        return $this->nonMaskedStorage;
479
+    }
480
+
481
+    public function getWrapperStorage() {
482
+        $this->init();
483
+        return $this->storage;
484
+    }
485
+
486
+    public function file_get_contents($path) {
487
+        $info = [
488
+            'target' => $this->getMountPoint() . '/' . $path,
489
+            'source' => $this->getUnjailedPath($path),
490
+        ];
491
+        \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info);
492
+        return parent::file_get_contents($path);
493
+    }
494
+
495
+    public function file_put_contents($path, $data) {
496
+        $info = [
497
+            'target' => $this->getMountPoint() . '/' . $path,
498
+            'source' => $this->getUnjailedPath($path),
499
+        ];
500
+        \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info);
501
+        return parent::file_put_contents($path, $data);
502
+    }
503
+
504
+    public function setMountOptions(array $options) {
505
+        $this->mountOptions = $options;
506
+    }
507 507
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
 	 * @return string
184 184
 	 */
185 185
 	public function getId() {
186
-		return 'shared::' . $this->getMountPoint();
186
+		return 'shared::'.$this->getMountPoint();
187 187
 	}
188 188
 
189 189
 	/**
@@ -286,7 +286,7 @@  discard block
 block discarded – undo
286 286
 					}
287 287
 			}
288 288
 			$info = [
289
-				'target' => $this->getMountPoint() . $path,
289
+				'target' => $this->getMountPoint().$path,
290 290
 				'source' => $source,
291 291
 				'mode' => $mode,
292 292
 			];
@@ -379,7 +379,7 @@  discard block
 block discarded – undo
379 379
 		if (!$storage) {
380 380
 			$storage = $this;
381 381
 		}
382
-		$sourceRoot  = $this->getSourceRootInfo();
382
+		$sourceRoot = $this->getSourceRootInfo();
383 383
 		if ($this->storage instanceof FailedStorage) {
384 384
 			return new FailedCache();
385 385
 		}
@@ -485,7 +485,7 @@  discard block
 block discarded – undo
485 485
 
486 486
 	public function file_get_contents($path) {
487 487
 		$info = [
488
-			'target' => $this->getMountPoint() . '/' . $path,
488
+			'target' => $this->getMountPoint().'/'.$path,
489 489
 			'source' => $this->getUnjailedPath($path),
490 490
 		];
491 491
 		\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info);
@@ -494,7 +494,7 @@  discard block
 block discarded – undo
494 494
 
495 495
 	public function file_put_contents($path, $data) {
496 496
 		$info = [
497
-			'target' => $this->getMountPoint() . '/' . $path,
497
+			'target' => $this->getMountPoint().'/'.$path,
498 498
 			'source' => $this->getUnjailedPath($path),
499 499
 		];
500 500
 		\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info);
Please login to merge, or discard this patch.
apps/files_sharing/lib/ShareBackend/Folder.php 1 patch
Indentation   +105 added lines, -105 removed lines patch added patch discarded remove patch
@@ -30,110 +30,110 @@
 block discarded – undo
30 30
 
31 31
 class Folder extends File implements \OCP\Share_Backend_Collection {
32 32
 
33
-	/**
34
-	 * get shared parents
35
-	 *
36
-	 * @param int $itemSource item source ID
37
-	 * @param string $shareWith with whom should the item be shared
38
-	 * @param string $owner owner of the item
39
-	 * @return array with shares
40
-	 */
41
-	public function getParents($itemSource, $shareWith = null, $owner = null) {
42
-		$result = [];
43
-		$parent = $this->getParentId($itemSource);
44
-
45
-		$userManager = \OC::$server->getUserManager();
46
-
47
-		while ($parent) {
48
-			$shares = \OCP\Share::getItemSharedWithUser('folder', $parent, $shareWith, $owner);
49
-			if ($shares) {
50
-				foreach ($shares as $share) {
51
-					$name = basename($share['path']);
52
-					$share['collection']['path'] = $name;
53
-					$share['collection']['item_type'] = 'folder';
54
-					$share['file_path'] = $name;
55
-
56
-					$ownerUser = $userManager->get($share['uid_owner']);
57
-					$displayNameOwner = $ownerUser === null ? $share['uid_owner'] : $ownerUser->getDisplayName();
58
-					$shareWithUser = $userManager->get($share['share_with']);
59
-					$displayNameShareWith = $shareWithUser === null ? $share['share_with'] : $shareWithUser->getDisplayName();
60
-					$share['displayname_owner'] = $displayNameOwner ? $displayNameOwner : $share['uid_owner'];
61
-					$share['share_with_displayname'] = $displayNameShareWith ? $displayNameShareWith : $share['uid_owner'];
62
-
63
-					$result[] = $share;
64
-				}
65
-			}
66
-			$parent = $this->getParentId($parent);
67
-		}
68
-
69
-		return $result;
70
-	}
71
-
72
-	/**
73
-	 * get file cache ID of parent
74
-	 *
75
-	 * @param int $child file cache ID of child
76
-	 * @return mixed parent ID or null
77
-	 */
78
-	private function getParentId($child) {
79
-		$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
80
-		$qb->select('parent')
81
-			->from('filecache')
82
-			->where(
83
-				$qb->expr()->eq('fileid', $qb->createNamedParameter($child))
84
-			);
85
-		$result = $qb->execute();
86
-		$row = $result->fetch();
87
-		$result->closeCursor();
88
-		return $row ? $row['parent'] : null;
89
-	}
90
-
91
-	public function getChildren($itemSource) {
92
-		$children = [];
93
-		$parents = [$itemSource];
94
-
95
-		$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
96
-		$qb->select('id')
97
-			->from('mimetypes')
98
-			->where(
99
-				$qb->expr()->eq('mimetype', $qb->createNamedParameter('httpd/unix-directory'))
100
-			);
101
-		$result = $qb->execute();
102
-		$row = $result->fetch();
103
-		$result->closeCursor();
104
-
105
-		if ($row = $result->fetchRow()) {
106
-			$mimetype = (int) $row['id'];
107
-		} else {
108
-			$mimetype = -1;
109
-		}
110
-		while (!empty($parents)) {
111
-
112
-			$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
113
-
114
-			$parents = array_map(function($parent) use ($qb) {
115
-				return $qb->createNamedParameter($parent);
116
-			}, $parents);
117
-
118
-			$qb->select('`fileid', 'name', '`mimetype')
119
-				->from('filecache')
120
-				->where(
121
-					$qb->expr()->in('parent', $parents)
122
-				);
123
-
124
-			$result = $qb->execute();
125
-
126
-			$parents = [];
127
-			while ($file = $result->fetch()) {
128
-				$children[] = ['source' => $file['fileid'], 'file_path' => $file['name']];
129
-				// If a child folder is found look inside it
130
-				if ((int) $file['mimetype'] === $mimetype) {
131
-					$parents[] = $file['fileid'];
132
-				}
133
-			}
134
-			$result->closeCursor();
135
-		}
136
-		return $children;
137
-	}
33
+    /**
34
+     * get shared parents
35
+     *
36
+     * @param int $itemSource item source ID
37
+     * @param string $shareWith with whom should the item be shared
38
+     * @param string $owner owner of the item
39
+     * @return array with shares
40
+     */
41
+    public function getParents($itemSource, $shareWith = null, $owner = null) {
42
+        $result = [];
43
+        $parent = $this->getParentId($itemSource);
44
+
45
+        $userManager = \OC::$server->getUserManager();
46
+
47
+        while ($parent) {
48
+            $shares = \OCP\Share::getItemSharedWithUser('folder', $parent, $shareWith, $owner);
49
+            if ($shares) {
50
+                foreach ($shares as $share) {
51
+                    $name = basename($share['path']);
52
+                    $share['collection']['path'] = $name;
53
+                    $share['collection']['item_type'] = 'folder';
54
+                    $share['file_path'] = $name;
55
+
56
+                    $ownerUser = $userManager->get($share['uid_owner']);
57
+                    $displayNameOwner = $ownerUser === null ? $share['uid_owner'] : $ownerUser->getDisplayName();
58
+                    $shareWithUser = $userManager->get($share['share_with']);
59
+                    $displayNameShareWith = $shareWithUser === null ? $share['share_with'] : $shareWithUser->getDisplayName();
60
+                    $share['displayname_owner'] = $displayNameOwner ? $displayNameOwner : $share['uid_owner'];
61
+                    $share['share_with_displayname'] = $displayNameShareWith ? $displayNameShareWith : $share['uid_owner'];
62
+
63
+                    $result[] = $share;
64
+                }
65
+            }
66
+            $parent = $this->getParentId($parent);
67
+        }
68
+
69
+        return $result;
70
+    }
71
+
72
+    /**
73
+     * get file cache ID of parent
74
+     *
75
+     * @param int $child file cache ID of child
76
+     * @return mixed parent ID or null
77
+     */
78
+    private function getParentId($child) {
79
+        $qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
80
+        $qb->select('parent')
81
+            ->from('filecache')
82
+            ->where(
83
+                $qb->expr()->eq('fileid', $qb->createNamedParameter($child))
84
+            );
85
+        $result = $qb->execute();
86
+        $row = $result->fetch();
87
+        $result->closeCursor();
88
+        return $row ? $row['parent'] : null;
89
+    }
90
+
91
+    public function getChildren($itemSource) {
92
+        $children = [];
93
+        $parents = [$itemSource];
94
+
95
+        $qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
96
+        $qb->select('id')
97
+            ->from('mimetypes')
98
+            ->where(
99
+                $qb->expr()->eq('mimetype', $qb->createNamedParameter('httpd/unix-directory'))
100
+            );
101
+        $result = $qb->execute();
102
+        $row = $result->fetch();
103
+        $result->closeCursor();
104
+
105
+        if ($row = $result->fetchRow()) {
106
+            $mimetype = (int) $row['id'];
107
+        } else {
108
+            $mimetype = -1;
109
+        }
110
+        while (!empty($parents)) {
111
+
112
+            $qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
113
+
114
+            $parents = array_map(function($parent) use ($qb) {
115
+                return $qb->createNamedParameter($parent);
116
+            }, $parents);
117
+
118
+            $qb->select('`fileid', 'name', '`mimetype')
119
+                ->from('filecache')
120
+                ->where(
121
+                    $qb->expr()->in('parent', $parents)
122
+                );
123
+
124
+            $result = $qb->execute();
125
+
126
+            $parents = [];
127
+            while ($file = $result->fetch()) {
128
+                $children[] = ['source' => $file['fileid'], 'file_path' => $file['name']];
129
+                // If a child folder is found look inside it
130
+                if ((int) $file['mimetype'] === $mimetype) {
131
+                    $parents[] = $file['fileid'];
132
+                }
133
+            }
134
+            $result->closeCursor();
135
+        }
136
+        return $children;
137
+    }
138 138
 
139 139
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/ShareBackend/File.php 1 patch
Indentation   +215 added lines, -215 removed lines patch added patch discarded remove patch
@@ -37,219 +37,219 @@
 block discarded – undo
37 37
 
38 38
 class File implements \OCP\Share_Backend_File_Dependent {
39 39
 
40
-	const FORMAT_SHARED_STORAGE = 0;
41
-	const FORMAT_GET_FOLDER_CONTENTS = 1;
42
-	const FORMAT_FILE_APP_ROOT = 2;
43
-	const FORMAT_OPENDIR = 3;
44
-	const FORMAT_GET_ALL = 4;
45
-	const FORMAT_PERMISSIONS = 5;
46
-	const FORMAT_TARGET_NAMES = 6;
47
-
48
-	private $path;
49
-
50
-	/** @var FederatedShareProvider */
51
-	private $federatedShareProvider;
52
-
53
-	public function __construct(FederatedShareProvider $federatedShareProvider = null) {
54
-		if ($federatedShareProvider) {
55
-			$this->federatedShareProvider = $federatedShareProvider;
56
-		} else {
57
-			$federatedSharingApp = new \OCA\FederatedFileSharing\AppInfo\Application();
58
-			$this->federatedShareProvider = $federatedSharingApp->getFederatedShareProvider();
59
-		}
60
-	}
61
-
62
-	public function isValidSource($itemSource, $uidOwner) {
63
-		try {
64
-			$path = \OC\Files\Filesystem::getPath($itemSource);
65
-			// FIXME: attributes should not be set here,
66
-			// keeping this pattern for now to avoid unexpected
67
-			// regressions
68
-			$this->path = \OC\Files\Filesystem::normalizePath(basename($path));
69
-			return true;
70
-		} catch (\OCP\Files\NotFoundException $e) {
71
-			return false;
72
-		}
73
-	}
74
-
75
-	public function getFilePath($itemSource, $uidOwner) {
76
-		if (isset($this->path)) {
77
-			$path = $this->path;
78
-			$this->path = null;
79
-			return $path;
80
-		} else {
81
-			try {
82
-				$path = \OC\Files\Filesystem::getPath($itemSource);
83
-				return $path;
84
-			} catch (\OCP\Files\NotFoundException $e) {
85
-				return false;
86
-			}
87
-		}
88
-	}
89
-
90
-	/**
91
-	 * create unique target
92
-	 * @param string $filePath
93
-	 * @param string $shareWith
94
-	 * @param array $exclude (optional)
95
-	 * @return string
96
-	 */
97
-	public function generateTarget($filePath, $shareWith, $exclude = null) {
98
-		$shareFolder = \OCA\Files_Sharing\Helper::getShareFolder();
99
-		$target = \OC\Files\Filesystem::normalizePath($shareFolder . '/' . basename($filePath));
100
-
101
-		// for group shares we return the target right away
102
-		if ($shareWith === false) {
103
-			return $target;
104
-		}
105
-
106
-		\OC\Files\Filesystem::initMountPoints($shareWith);
107
-		$view = new \OC\Files\View('/' . $shareWith . '/files');
108
-
109
-		if (!$view->is_dir($shareFolder)) {
110
-			$dir = '';
111
-			$subdirs = explode('/', $shareFolder);
112
-			foreach ($subdirs as $subdir) {
113
-				$dir = $dir . '/' . $subdir;
114
-				if (!$view->is_dir($dir)) {
115
-					$view->mkdir($dir);
116
-				}
117
-			}
118
-		}
119
-
120
-		$excludeList = is_array($exclude) ? $exclude : [];
121
-
122
-		return \OCA\Files_Sharing\Helper::generateUniqueTarget($target, $excludeList, $view);
123
-	}
124
-
125
-	public function formatItems($items, $format, $parameters = null) {
126
-		if ($format === self::FORMAT_SHARED_STORAGE) {
127
-			// Only 1 item should come through for this format call
128
-			$item = array_shift($items);
129
-			return [
130
-				'parent' => $item['parent'],
131
-				'path' => $item['path'],
132
-				'storage' => $item['storage'],
133
-				'permissions' => $item['permissions'],
134
-				'uid_owner' => $item['uid_owner'],
135
-			];
136
-		} else if ($format === self::FORMAT_GET_FOLDER_CONTENTS) {
137
-			$files = [];
138
-			foreach ($items as $item) {
139
-				$file = [];
140
-				$file['fileid'] = $item['file_source'];
141
-				$file['storage'] = $item['storage'];
142
-				$file['path'] = $item['file_target'];
143
-				$file['parent'] = $item['file_parent'];
144
-				$file['name'] = basename($item['file_target']);
145
-				$file['mimetype'] = $item['mimetype'];
146
-				$file['mimepart'] = $item['mimepart'];
147
-				$file['mtime'] = $item['mtime'];
148
-				$file['encrypted'] = $item['encrypted'];
149
-				$file['etag'] = $item['etag'];
150
-				$file['uid_owner'] = $item['uid_owner'];
151
-				$file['displayname_owner'] = $item['displayname_owner'];
152
-
153
-				$storage = \OC\Files\Filesystem::getStorage('/');
154
-				$cache = $storage->getCache();
155
-				$file['size'] = $item['size'];
156
-				$files[] = $file;
157
-			}
158
-			return $files;
159
-		} else if ($format === self::FORMAT_OPENDIR) {
160
-			$files = [];
161
-			foreach ($items as $item) {
162
-				$files[] = basename($item['file_target']);
163
-			}
164
-			return $files;
165
-		} else if ($format === self::FORMAT_GET_ALL) {
166
-			$ids = [];
167
-			foreach ($items as $item) {
168
-				$ids[] = $item['file_source'];
169
-			}
170
-			return $ids;
171
-		} else if ($format === self::FORMAT_PERMISSIONS) {
172
-			$filePermissions = [];
173
-			foreach ($items as $item) {
174
-				$filePermissions[$item['file_source']] = $item['permissions'];
175
-			}
176
-			return $filePermissions;
177
-		} else if ($format === self::FORMAT_TARGET_NAMES) {
178
-			$targets = [];
179
-			foreach ($items as $item) {
180
-				$targets[] = $item['file_target'];
181
-			}
182
-			return $targets;
183
-		}
184
-		return [];
185
-	}
186
-
187
-	/**
188
-	 * check if server2server share is enabled
189
-	 *
190
-	 * @param int $shareType
191
-	 * @return boolean
192
-	 */
193
-	public function isShareTypeAllowed($shareType) {
194
-		if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
195
-			return $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
196
-		}
197
-
198
-		if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
199
-			return $this->federatedShareProvider->isOutgoingServer2serverGroupShareEnabled();
200
-		}
201
-
202
-		return true;
203
-	}
204
-
205
-	/**
206
-	 * resolve reshares to return the correct source item
207
-	 * @param array $source
208
-	 * @return array source item
209
-	 */
210
-	protected static function resolveReshares($source) {
211
-		if (isset($source['parent'])) {
212
-			$parent = $source['parent'];
213
-			while (isset($parent)) {
214
-				$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
215
-				$qb->select('parent', 'uid_owner')
216
-					->from('share')
217
-					->where(
218
-						$qb->expr()->eq('id', $qb->createNamedParameter($parent))
219
-					);
220
-				$result = $qb->execute();
221
-				$item = $result->fetch();
222
-				$result->closeCursor();
223
-				if (isset($item['parent'])) {
224
-					$parent = $item['parent'];
225
-				} else {
226
-					$fileOwner = $item['uid_owner'];
227
-					break;
228
-				}
229
-			}
230
-		} else {
231
-			$fileOwner = $source['uid_owner'];
232
-		}
233
-		if (isset($fileOwner)) {
234
-			$source['fileOwner'] = $fileOwner;
235
-		} else {
236
-			\OC::$server->getLogger()->error('No owner found for reshare', ['app' => 'files_sharing']);
237
-		}
238
-
239
-		return $source;
240
-	}
241
-
242
-	/**
243
-	 * @param string $target
244
-	 * @param array $share
245
-	 * @return array|false source item
246
-	 */
247
-	public static function getSource($target, $share) {
248
-		if ($share['item_type'] === 'folder' && $target !== '') {
249
-			// note: in case of ext storage mount points the path might be empty
250
-			// which would cause a leading slash to appear
251
-			$share['path'] = ltrim($share['path'] . '/' . $target, '/');
252
-		}
253
-		return self::resolveReshares($share);
254
-	}
40
+    const FORMAT_SHARED_STORAGE = 0;
41
+    const FORMAT_GET_FOLDER_CONTENTS = 1;
42
+    const FORMAT_FILE_APP_ROOT = 2;
43
+    const FORMAT_OPENDIR = 3;
44
+    const FORMAT_GET_ALL = 4;
45
+    const FORMAT_PERMISSIONS = 5;
46
+    const FORMAT_TARGET_NAMES = 6;
47
+
48
+    private $path;
49
+
50
+    /** @var FederatedShareProvider */
51
+    private $federatedShareProvider;
52
+
53
+    public function __construct(FederatedShareProvider $federatedShareProvider = null) {
54
+        if ($federatedShareProvider) {
55
+            $this->federatedShareProvider = $federatedShareProvider;
56
+        } else {
57
+            $federatedSharingApp = new \OCA\FederatedFileSharing\AppInfo\Application();
58
+            $this->federatedShareProvider = $federatedSharingApp->getFederatedShareProvider();
59
+        }
60
+    }
61
+
62
+    public function isValidSource($itemSource, $uidOwner) {
63
+        try {
64
+            $path = \OC\Files\Filesystem::getPath($itemSource);
65
+            // FIXME: attributes should not be set here,
66
+            // keeping this pattern for now to avoid unexpected
67
+            // regressions
68
+            $this->path = \OC\Files\Filesystem::normalizePath(basename($path));
69
+            return true;
70
+        } catch (\OCP\Files\NotFoundException $e) {
71
+            return false;
72
+        }
73
+    }
74
+
75
+    public function getFilePath($itemSource, $uidOwner) {
76
+        if (isset($this->path)) {
77
+            $path = $this->path;
78
+            $this->path = null;
79
+            return $path;
80
+        } else {
81
+            try {
82
+                $path = \OC\Files\Filesystem::getPath($itemSource);
83
+                return $path;
84
+            } catch (\OCP\Files\NotFoundException $e) {
85
+                return false;
86
+            }
87
+        }
88
+    }
89
+
90
+    /**
91
+     * create unique target
92
+     * @param string $filePath
93
+     * @param string $shareWith
94
+     * @param array $exclude (optional)
95
+     * @return string
96
+     */
97
+    public function generateTarget($filePath, $shareWith, $exclude = null) {
98
+        $shareFolder = \OCA\Files_Sharing\Helper::getShareFolder();
99
+        $target = \OC\Files\Filesystem::normalizePath($shareFolder . '/' . basename($filePath));
100
+
101
+        // for group shares we return the target right away
102
+        if ($shareWith === false) {
103
+            return $target;
104
+        }
105
+
106
+        \OC\Files\Filesystem::initMountPoints($shareWith);
107
+        $view = new \OC\Files\View('/' . $shareWith . '/files');
108
+
109
+        if (!$view->is_dir($shareFolder)) {
110
+            $dir = '';
111
+            $subdirs = explode('/', $shareFolder);
112
+            foreach ($subdirs as $subdir) {
113
+                $dir = $dir . '/' . $subdir;
114
+                if (!$view->is_dir($dir)) {
115
+                    $view->mkdir($dir);
116
+                }
117
+            }
118
+        }
119
+
120
+        $excludeList = is_array($exclude) ? $exclude : [];
121
+
122
+        return \OCA\Files_Sharing\Helper::generateUniqueTarget($target, $excludeList, $view);
123
+    }
124
+
125
+    public function formatItems($items, $format, $parameters = null) {
126
+        if ($format === self::FORMAT_SHARED_STORAGE) {
127
+            // Only 1 item should come through for this format call
128
+            $item = array_shift($items);
129
+            return [
130
+                'parent' => $item['parent'],
131
+                'path' => $item['path'],
132
+                'storage' => $item['storage'],
133
+                'permissions' => $item['permissions'],
134
+                'uid_owner' => $item['uid_owner'],
135
+            ];
136
+        } else if ($format === self::FORMAT_GET_FOLDER_CONTENTS) {
137
+            $files = [];
138
+            foreach ($items as $item) {
139
+                $file = [];
140
+                $file['fileid'] = $item['file_source'];
141
+                $file['storage'] = $item['storage'];
142
+                $file['path'] = $item['file_target'];
143
+                $file['parent'] = $item['file_parent'];
144
+                $file['name'] = basename($item['file_target']);
145
+                $file['mimetype'] = $item['mimetype'];
146
+                $file['mimepart'] = $item['mimepart'];
147
+                $file['mtime'] = $item['mtime'];
148
+                $file['encrypted'] = $item['encrypted'];
149
+                $file['etag'] = $item['etag'];
150
+                $file['uid_owner'] = $item['uid_owner'];
151
+                $file['displayname_owner'] = $item['displayname_owner'];
152
+
153
+                $storage = \OC\Files\Filesystem::getStorage('/');
154
+                $cache = $storage->getCache();
155
+                $file['size'] = $item['size'];
156
+                $files[] = $file;
157
+            }
158
+            return $files;
159
+        } else if ($format === self::FORMAT_OPENDIR) {
160
+            $files = [];
161
+            foreach ($items as $item) {
162
+                $files[] = basename($item['file_target']);
163
+            }
164
+            return $files;
165
+        } else if ($format === self::FORMAT_GET_ALL) {
166
+            $ids = [];
167
+            foreach ($items as $item) {
168
+                $ids[] = $item['file_source'];
169
+            }
170
+            return $ids;
171
+        } else if ($format === self::FORMAT_PERMISSIONS) {
172
+            $filePermissions = [];
173
+            foreach ($items as $item) {
174
+                $filePermissions[$item['file_source']] = $item['permissions'];
175
+            }
176
+            return $filePermissions;
177
+        } else if ($format === self::FORMAT_TARGET_NAMES) {
178
+            $targets = [];
179
+            foreach ($items as $item) {
180
+                $targets[] = $item['file_target'];
181
+            }
182
+            return $targets;
183
+        }
184
+        return [];
185
+    }
186
+
187
+    /**
188
+     * check if server2server share is enabled
189
+     *
190
+     * @param int $shareType
191
+     * @return boolean
192
+     */
193
+    public function isShareTypeAllowed($shareType) {
194
+        if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
195
+            return $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
196
+        }
197
+
198
+        if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
199
+            return $this->federatedShareProvider->isOutgoingServer2serverGroupShareEnabled();
200
+        }
201
+
202
+        return true;
203
+    }
204
+
205
+    /**
206
+     * resolve reshares to return the correct source item
207
+     * @param array $source
208
+     * @return array source item
209
+     */
210
+    protected static function resolveReshares($source) {
211
+        if (isset($source['parent'])) {
212
+            $parent = $source['parent'];
213
+            while (isset($parent)) {
214
+                $qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
215
+                $qb->select('parent', 'uid_owner')
216
+                    ->from('share')
217
+                    ->where(
218
+                        $qb->expr()->eq('id', $qb->createNamedParameter($parent))
219
+                    );
220
+                $result = $qb->execute();
221
+                $item = $result->fetch();
222
+                $result->closeCursor();
223
+                if (isset($item['parent'])) {
224
+                    $parent = $item['parent'];
225
+                } else {
226
+                    $fileOwner = $item['uid_owner'];
227
+                    break;
228
+                }
229
+            }
230
+        } else {
231
+            $fileOwner = $source['uid_owner'];
232
+        }
233
+        if (isset($fileOwner)) {
234
+            $source['fileOwner'] = $fileOwner;
235
+        } else {
236
+            \OC::$server->getLogger()->error('No owner found for reshare', ['app' => 'files_sharing']);
237
+        }
238
+
239
+        return $source;
240
+    }
241
+
242
+    /**
243
+     * @param string $target
244
+     * @param array $share
245
+     * @return array|false source item
246
+     */
247
+    public static function getSource($target, $share) {
248
+        if ($share['item_type'] === 'folder' && $target !== '') {
249
+            // note: in case of ext storage mount points the path might be empty
250
+            // which would cause a leading slash to appear
251
+            $share['path'] = ltrim($share['path'] . '/' . $target, '/');
252
+        }
253
+        return self::resolveReshares($share);
254
+    }
255 255
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/Controller/ShareController.php 2 patches
Indentation   +643 added lines, -644 removed lines patch added patch discarded remove patch
@@ -80,652 +80,651 @@
 block discarded – undo
80 80
  */
81 81
 class ShareController extends AuthPublicShareController {
82 82
 
83
-	/** @var IConfig */
84
-	protected $config;
85
-	/** @var IUserManager */
86
-	protected $userManager;
87
-	/** @var ILogger */
88
-	protected $logger;
89
-	/** @var \OCP\Activity\IManager */
90
-	protected $activityManager;
91
-	/** @var IPreview */
92
-	protected $previewManager;
93
-	/** @var IRootFolder */
94
-	protected $rootFolder;
95
-	/** @var FederatedShareProvider */
96
-	protected $federatedShareProvider;
97
-	/** @var EventDispatcherInterface */
98
-	protected $eventDispatcher;
99
-	/** @var IL10N */
100
-	protected $l10n;
101
-	/** @var Defaults */
102
-	protected $defaults;
103
-	/** @var ShareManager */
104
-	protected $shareManager;
105
-
106
-	/** @var Share\IShare */
107
-	protected $share;
108
-
109
-	/**
110
-	 * @param string $appName
111
-	 * @param IRequest $request
112
-	 * @param IConfig $config
113
-	 * @param IURLGenerator $urlGenerator
114
-	 * @param IUserManager $userManager
115
-	 * @param ILogger $logger
116
-	 * @param \OCP\Activity\IManager $activityManager
117
-	 * @param \OCP\Share\IManager $shareManager
118
-	 * @param ISession $session
119
-	 * @param IPreview $previewManager
120
-	 * @param IRootFolder $rootFolder
121
-	 * @param FederatedShareProvider $federatedShareProvider
122
-	 * @param EventDispatcherInterface $eventDispatcher
123
-	 * @param IL10N $l10n
124
-	 * @param Defaults $defaults
125
-	 */
126
-	public function __construct(string $appName,
127
-								IRequest $request,
128
-								IConfig $config,
129
-								IURLGenerator $urlGenerator,
130
-								IUserManager $userManager,
131
-								ILogger $logger,
132
-								\OCP\Activity\IManager $activityManager,
133
-								ShareManager $shareManager,
134
-								ISession $session,
135
-								IPreview $previewManager,
136
-								IRootFolder $rootFolder,
137
-								FederatedShareProvider $federatedShareProvider,
138
-								EventDispatcherInterface $eventDispatcher,
139
-								IL10N $l10n,
140
-								Defaults $defaults) {
141
-		parent::__construct($appName, $request, $session, $urlGenerator);
142
-
143
-		$this->config = $config;
144
-		$this->userManager = $userManager;
145
-		$this->logger = $logger;
146
-		$this->activityManager = $activityManager;
147
-		$this->previewManager = $previewManager;
148
-		$this->rootFolder = $rootFolder;
149
-		$this->federatedShareProvider = $federatedShareProvider;
150
-		$this->eventDispatcher = $eventDispatcher;
151
-		$this->l10n = $l10n;
152
-		$this->defaults = $defaults;
153
-		$this->shareManager = $shareManager;
154
-	}
155
-
156
-	/**
157
-	 * @PublicPage
158
-	 * @NoCSRFRequired
159
-	 *
160
-	 * Show the authentication page
161
-	 * The form has to submit to the authenticate method route
162
-	 */
163
-	public function showAuthenticate(): TemplateResponse {
164
-		$templateParameters = ['share' => $this->share];
165
-
166
-		$event = new GenericEvent(null, $templateParameters);
167
-		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
168
-
169
-		$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
170
-		if ($this->share->getSendPasswordByTalk()) {
171
-			$csp = new ContentSecurityPolicy();
172
-			$csp->addAllowedConnectDomain('*');
173
-			$csp->addAllowedMediaDomain('blob:');
174
-			$response->setContentSecurityPolicy($csp);
175
-		}
176
-
177
-		return $response;
178
-	}
179
-
180
-	/**
181
-	 * The template to show when authentication failed
182
-	 */
183
-	protected function showAuthFailed(): TemplateResponse {
184
-		$templateParameters = ['share' => $this->share, 'wrongpw' => true];
185
-
186
-		$event = new GenericEvent(null, $templateParameters);
187
-		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
188
-
189
-		$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
190
-		if ($this->share->getSendPasswordByTalk()) {
191
-			$csp = new ContentSecurityPolicy();
192
-			$csp->addAllowedConnectDomain('*');
193
-			$csp->addAllowedMediaDomain('blob:');
194
-			$response->setContentSecurityPolicy($csp);
195
-		}
196
-
197
-		return $response;
198
-	}
199
-
200
-	protected function verifyPassword(string $password): bool {
201
-		return $this->shareManager->checkPassword($this->share, $password);
202
-	}
203
-
204
-	protected function getPasswordHash(): string {
205
-		return $this->share->getPassword();
206
-	}
207
-
208
-	public function isValidToken(): bool {
209
-		try {
210
-			$this->share = $this->shareManager->getShareByToken($this->getToken());
211
-		} catch (ShareNotFound $e) {
212
-			return false;
213
-		}
214
-
215
-		return true;
216
-	}
217
-
218
-	protected function isPasswordProtected(): bool {
219
-		return $this->share->getPassword() !== null;
220
-	}
221
-
222
-	protected function authSucceeded() {
223
-		// For share this was always set so it is still used in other apps
224
-		$this->session->set('public_link_authenticated', (string)$this->share->getId());
225
-	}
226
-
227
-	protected function authFailed() {
228
-		$this->emitAccessShareHook($this->share, 403, 'Wrong password');
229
-	}
230
-
231
-	/**
232
-	 * throws hooks when a share is attempted to be accessed
233
-	 *
234
-	 * @param \OCP\Share\IShare|string $share the Share instance if available,
235
-	 * otherwise token
236
-	 * @param int $errorCode
237
-	 * @param string $errorMessage
238
-	 * @throws \OC\HintException
239
-	 * @throws \OC\ServerNotAvailableException
240
-	 */
241
-	protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
242
-		$itemType = $itemSource = $uidOwner = '';
243
-		$token = $share;
244
-		$exception = null;
245
-		if($share instanceof \OCP\Share\IShare) {
246
-			try {
247
-				$token = $share->getToken();
248
-				$uidOwner = $share->getSharedBy();
249
-				$itemType = $share->getNodeType();
250
-				$itemSource = $share->getNodeId();
251
-			} catch (\Exception $e) {
252
-				// we log what we know and pass on the exception afterwards
253
-				$exception = $e;
254
-			}
255
-		}
256
-		\OC_Hook::emit(Share::class, 'share_link_access', [
257
-			'itemType' => $itemType,
258
-			'itemSource' => $itemSource,
259
-			'uidOwner' => $uidOwner,
260
-			'token' => $token,
261
-			'errorCode' => $errorCode,
262
-			'errorMessage' => $errorMessage,
263
-		]);
264
-		if(!is_null($exception)) {
265
-			throw $exception;
266
-		}
267
-	}
268
-
269
-	/**
270
-	 * Validate the permissions of the share
271
-	 *
272
-	 * @param Share\IShare $share
273
-	 * @return bool
274
-	 */
275
-	private function validateShare(\OCP\Share\IShare $share) {
276
-		// If the owner is disabled no access to the linke is granted
277
-		$owner = $this->userManager->get($share->getShareOwner());
278
-		if ($owner === null || !$owner->isEnabled()) {
279
-			return false;
280
-		}
281
-
282
-		// If the initiator of the share is disabled no access is granted
283
-		$initiator = $this->userManager->get($share->getSharedBy());
284
-		if ($initiator === null || !$initiator->isEnabled()) {
285
-			return false;
286
-		}
287
-
288
-		return $share->getNode()->isReadable() && $share->getNode()->isShareable();
289
-	}
290
-
291
-	/**
292
-	 * @PublicPage
293
-	 * @NoCSRFRequired
294
-	 *
295
-
296
-	 * @param string $path
297
-	 * @return TemplateResponse
298
-	 * @throws NotFoundException
299
-	 * @throws \Exception
300
-	 */
301
-	public function showShare($path = ''): TemplateResponse {
302
-		\OC_User::setIncognitoMode(true);
303
-
304
-		// Check whether share exists
305
-		try {
306
-			$share = $this->shareManager->getShareByToken($this->getToken());
307
-		} catch (ShareNotFound $e) {
308
-			$this->emitAccessShareHook($this->getToken(), 404, 'Share not found');
309
-			throw new NotFoundException();
310
-		}
311
-
312
-		if (!$this->validateShare($share)) {
313
-			throw new NotFoundException();
314
-		}
315
-
316
-		$shareNode = $share->getNode();
317
-
318
-		// We can't get the path of a file share
319
-		try {
320
-			if ($shareNode instanceof \OCP\Files\File && $path !== '') {
321
-				$this->emitAccessShareHook($share, 404, 'Share not found');
322
-				throw new NotFoundException();
323
-			}
324
-		} catch (\Exception $e) {
325
-			$this->emitAccessShareHook($share, 404, 'Share not found');
326
-			throw $e;
327
-		}
328
-
329
-		$shareTmpl = [];
330
-		$shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
331
-		$shareTmpl['owner'] = $share->getShareOwner();
332
-		$shareTmpl['filename'] = $shareNode->getName();
333
-		$shareTmpl['directory_path'] = $share->getTarget();
334
-		$shareTmpl['note'] = $share->getNote();
335
-		$shareTmpl['mimetype'] = $shareNode->getMimetype();
336
-		$shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
337
-		$shareTmpl['dirToken'] = $this->getToken();
338
-		$shareTmpl['sharingToken'] = $this->getToken();
339
-		$shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
340
-		$shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
341
-		$shareTmpl['dir'] = '';
342
-		$shareTmpl['nonHumanFileSize'] = $shareNode->getSize();
343
-		$shareTmpl['fileSize'] = \OCP\Util::humanFileSize($shareNode->getSize());
344
-		$shareTmpl['hideDownload'] = $share->getHideDownload();
345
-
346
-		$hideFileList = false;
347
-
348
-		if ($shareNode instanceof \OCP\Files\Folder) {
349
-
350
-			$shareIsFolder = true;
351
-
352
-			try {
353
-				$folderNode = $shareNode->get($path);
354
-			} catch (\OCP\Files\NotFoundException $e) {
355
-				$this->emitAccessShareHook($share, 404, 'Share not found');
356
-				throw new NotFoundException();
357
-			}
358
-
359
-			$shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath());
360
-
361
-			/*
83
+    /** @var IConfig */
84
+    protected $config;
85
+    /** @var IUserManager */
86
+    protected $userManager;
87
+    /** @var ILogger */
88
+    protected $logger;
89
+    /** @var \OCP\Activity\IManager */
90
+    protected $activityManager;
91
+    /** @var IPreview */
92
+    protected $previewManager;
93
+    /** @var IRootFolder */
94
+    protected $rootFolder;
95
+    /** @var FederatedShareProvider */
96
+    protected $federatedShareProvider;
97
+    /** @var EventDispatcherInterface */
98
+    protected $eventDispatcher;
99
+    /** @var IL10N */
100
+    protected $l10n;
101
+    /** @var Defaults */
102
+    protected $defaults;
103
+    /** @var ShareManager */
104
+    protected $shareManager;
105
+
106
+    /** @var Share\IShare */
107
+    protected $share;
108
+
109
+    /**
110
+     * @param string $appName
111
+     * @param IRequest $request
112
+     * @param IConfig $config
113
+     * @param IURLGenerator $urlGenerator
114
+     * @param IUserManager $userManager
115
+     * @param ILogger $logger
116
+     * @param \OCP\Activity\IManager $activityManager
117
+     * @param \OCP\Share\IManager $shareManager
118
+     * @param ISession $session
119
+     * @param IPreview $previewManager
120
+     * @param IRootFolder $rootFolder
121
+     * @param FederatedShareProvider $federatedShareProvider
122
+     * @param EventDispatcherInterface $eventDispatcher
123
+     * @param IL10N $l10n
124
+     * @param Defaults $defaults
125
+     */
126
+    public function __construct(string $appName,
127
+                                IRequest $request,
128
+                                IConfig $config,
129
+                                IURLGenerator $urlGenerator,
130
+                                IUserManager $userManager,
131
+                                ILogger $logger,
132
+                                \OCP\Activity\IManager $activityManager,
133
+                                ShareManager $shareManager,
134
+                                ISession $session,
135
+                                IPreview $previewManager,
136
+                                IRootFolder $rootFolder,
137
+                                FederatedShareProvider $federatedShareProvider,
138
+                                EventDispatcherInterface $eventDispatcher,
139
+                                IL10N $l10n,
140
+                                Defaults $defaults) {
141
+        parent::__construct($appName, $request, $session, $urlGenerator);
142
+
143
+        $this->config = $config;
144
+        $this->userManager = $userManager;
145
+        $this->logger = $logger;
146
+        $this->activityManager = $activityManager;
147
+        $this->previewManager = $previewManager;
148
+        $this->rootFolder = $rootFolder;
149
+        $this->federatedShareProvider = $federatedShareProvider;
150
+        $this->eventDispatcher = $eventDispatcher;
151
+        $this->l10n = $l10n;
152
+        $this->defaults = $defaults;
153
+        $this->shareManager = $shareManager;
154
+    }
155
+
156
+    /**
157
+     * @PublicPage
158
+     * @NoCSRFRequired
159
+     *
160
+     * Show the authentication page
161
+     * The form has to submit to the authenticate method route
162
+     */
163
+    public function showAuthenticate(): TemplateResponse {
164
+        $templateParameters = ['share' => $this->share];
165
+
166
+        $event = new GenericEvent(null, $templateParameters);
167
+        $this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
168
+
169
+        $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
170
+        if ($this->share->getSendPasswordByTalk()) {
171
+            $csp = new ContentSecurityPolicy();
172
+            $csp->addAllowedConnectDomain('*');
173
+            $csp->addAllowedMediaDomain('blob:');
174
+            $response->setContentSecurityPolicy($csp);
175
+        }
176
+
177
+        return $response;
178
+    }
179
+
180
+    /**
181
+     * The template to show when authentication failed
182
+     */
183
+    protected function showAuthFailed(): TemplateResponse {
184
+        $templateParameters = ['share' => $this->share, 'wrongpw' => true];
185
+
186
+        $event = new GenericEvent(null, $templateParameters);
187
+        $this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
188
+
189
+        $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
190
+        if ($this->share->getSendPasswordByTalk()) {
191
+            $csp = new ContentSecurityPolicy();
192
+            $csp->addAllowedConnectDomain('*');
193
+            $csp->addAllowedMediaDomain('blob:');
194
+            $response->setContentSecurityPolicy($csp);
195
+        }
196
+
197
+        return $response;
198
+    }
199
+
200
+    protected function verifyPassword(string $password): bool {
201
+        return $this->shareManager->checkPassword($this->share, $password);
202
+    }
203
+
204
+    protected function getPasswordHash(): string {
205
+        return $this->share->getPassword();
206
+    }
207
+
208
+    public function isValidToken(): bool {
209
+        try {
210
+            $this->share = $this->shareManager->getShareByToken($this->getToken());
211
+        } catch (ShareNotFound $e) {
212
+            return false;
213
+        }
214
+
215
+        return true;
216
+    }
217
+
218
+    protected function isPasswordProtected(): bool {
219
+        return $this->share->getPassword() !== null;
220
+    }
221
+
222
+    protected function authSucceeded() {
223
+        // For share this was always set so it is still used in other apps
224
+        $this->session->set('public_link_authenticated', (string)$this->share->getId());
225
+    }
226
+
227
+    protected function authFailed() {
228
+        $this->emitAccessShareHook($this->share, 403, 'Wrong password');
229
+    }
230
+
231
+    /**
232
+     * throws hooks when a share is attempted to be accessed
233
+     *
234
+     * @param \OCP\Share\IShare|string $share the Share instance if available,
235
+     * otherwise token
236
+     * @param int $errorCode
237
+     * @param string $errorMessage
238
+     * @throws \OC\HintException
239
+     * @throws \OC\ServerNotAvailableException
240
+     */
241
+    protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
242
+        $itemType = $itemSource = $uidOwner = '';
243
+        $token = $share;
244
+        $exception = null;
245
+        if($share instanceof \OCP\Share\IShare) {
246
+            try {
247
+                $token = $share->getToken();
248
+                $uidOwner = $share->getSharedBy();
249
+                $itemType = $share->getNodeType();
250
+                $itemSource = $share->getNodeId();
251
+            } catch (\Exception $e) {
252
+                // we log what we know and pass on the exception afterwards
253
+                $exception = $e;
254
+            }
255
+        }
256
+        \OC_Hook::emit(Share::class, 'share_link_access', [
257
+            'itemType' => $itemType,
258
+            'itemSource' => $itemSource,
259
+            'uidOwner' => $uidOwner,
260
+            'token' => $token,
261
+            'errorCode' => $errorCode,
262
+            'errorMessage' => $errorMessage,
263
+        ]);
264
+        if(!is_null($exception)) {
265
+            throw $exception;
266
+        }
267
+    }
268
+
269
+    /**
270
+     * Validate the permissions of the share
271
+     *
272
+     * @param Share\IShare $share
273
+     * @return bool
274
+     */
275
+    private function validateShare(\OCP\Share\IShare $share) {
276
+        // If the owner is disabled no access to the linke is granted
277
+        $owner = $this->userManager->get($share->getShareOwner());
278
+        if ($owner === null || !$owner->isEnabled()) {
279
+            return false;
280
+        }
281
+
282
+        // If the initiator of the share is disabled no access is granted
283
+        $initiator = $this->userManager->get($share->getSharedBy());
284
+        if ($initiator === null || !$initiator->isEnabled()) {
285
+            return false;
286
+        }
287
+
288
+        return $share->getNode()->isReadable() && $share->getNode()->isShareable();
289
+    }
290
+
291
+    /**
292
+     * @PublicPage
293
+     * @NoCSRFRequired
294
+     *
295
+     * @param string $path
296
+     * @return TemplateResponse
297
+     * @throws NotFoundException
298
+     * @throws \Exception
299
+     */
300
+    public function showShare($path = ''): TemplateResponse {
301
+        \OC_User::setIncognitoMode(true);
302
+
303
+        // Check whether share exists
304
+        try {
305
+            $share = $this->shareManager->getShareByToken($this->getToken());
306
+        } catch (ShareNotFound $e) {
307
+            $this->emitAccessShareHook($this->getToken(), 404, 'Share not found');
308
+            throw new NotFoundException();
309
+        }
310
+
311
+        if (!$this->validateShare($share)) {
312
+            throw new NotFoundException();
313
+        }
314
+
315
+        $shareNode = $share->getNode();
316
+
317
+        // We can't get the path of a file share
318
+        try {
319
+            if ($shareNode instanceof \OCP\Files\File && $path !== '') {
320
+                $this->emitAccessShareHook($share, 404, 'Share not found');
321
+                throw new NotFoundException();
322
+            }
323
+        } catch (\Exception $e) {
324
+            $this->emitAccessShareHook($share, 404, 'Share not found');
325
+            throw $e;
326
+        }
327
+
328
+        $shareTmpl = [];
329
+        $shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
330
+        $shareTmpl['owner'] = $share->getShareOwner();
331
+        $shareTmpl['filename'] = $shareNode->getName();
332
+        $shareTmpl['directory_path'] = $share->getTarget();
333
+        $shareTmpl['note'] = $share->getNote();
334
+        $shareTmpl['mimetype'] = $shareNode->getMimetype();
335
+        $shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
336
+        $shareTmpl['dirToken'] = $this->getToken();
337
+        $shareTmpl['sharingToken'] = $this->getToken();
338
+        $shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
339
+        $shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
340
+        $shareTmpl['dir'] = '';
341
+        $shareTmpl['nonHumanFileSize'] = $shareNode->getSize();
342
+        $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($shareNode->getSize());
343
+        $shareTmpl['hideDownload'] = $share->getHideDownload();
344
+
345
+        $hideFileList = false;
346
+
347
+        if ($shareNode instanceof \OCP\Files\Folder) {
348
+
349
+            $shareIsFolder = true;
350
+
351
+            try {
352
+                $folderNode = $shareNode->get($path);
353
+            } catch (\OCP\Files\NotFoundException $e) {
354
+                $this->emitAccessShareHook($share, 404, 'Share not found');
355
+                throw new NotFoundException();
356
+            }
357
+
358
+            $shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath());
359
+
360
+            /*
362 361
 			 * The OC_Util methods require a view. This just uses the node API
363 362
 			 */
364
-			$freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
365
-			if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
366
-				$freeSpace = max($freeSpace, 0);
367
-			} else {
368
-				$freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
369
-			}
370
-
371
-			$hideFileList = !($share->getPermissions() & \OCP\Constants::PERMISSION_READ);
372
-			$maxUploadFilesize = $freeSpace;
373
-
374
-			$folder = new Template('files', 'list', '');
375
-
376
-			$folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath()));
377
-			$folder->assign('dirToken', $this->getToken());
378
-			$folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
379
-			$folder->assign('isPublic', true);
380
-			$folder->assign('hideFileList', $hideFileList);
381
-			$folder->assign('publicUploadEnabled', 'no');
382
-			// default to list view
383
-			$folder->assign('showgridview', false);
384
-			$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
385
-			$folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
386
-			$folder->assign('freeSpace', $freeSpace);
387
-			$folder->assign('usedSpacePercent', 0);
388
-			$folder->assign('trash', false);
389
-			$shareTmpl['folder'] = $folder->fetchPage();
390
-		} else {
391
-			$shareIsFolder = false;
392
-		}
393
-
394
-		// default to list view
395
-		$shareTmpl['showgridview'] = false;
396
-
397
-		$shareTmpl['hideFileList'] = $hideFileList;
398
-		$shareTmpl['shareOwner'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
399
-		$shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', ['token' => $this->getToken()]);
400
-		$shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $this->getToken()]);
401
-		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
402
-		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
403
-		$shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
404
-		$shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
405
-		$shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
406
-		$shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
407
-
408
-		if ($shareTmpl['previewSupported']) {
409
-			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute( 'files_sharing.PublicPreview.getPreview',
410
-				['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
411
-			$ogPreview = $shareTmpl['previewImage'];
412
-
413
-			// We just have direct previews for image files
414
-			if ($shareNode->getMimePart() === 'image') {
415
-				$shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]);
416
-
417
-				$ogPreview = $shareTmpl['previewURL'];
418
-
419
-				//Whatapp is kind of picky about their size requirements
420
-				if ($this->request->isUserAgent(['/^WhatsApp/'])) {
421
-					$ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
422
-						'token' => $this->getToken(),
423
-						'x' => 256,
424
-						'y' => 256,
425
-						'a' => true,
426
-					]);
427
-				}
428
-			}
429
-		} else {
430
-			$shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
431
-			$ogPreview = $shareTmpl['previewImage'];
432
-		}
433
-
434
-		// Load files we need
435
-		\OCP\Util::addScript('files', 'semaphore');
436
-		\OCP\Util::addScript('files', 'file-upload');
437
-		\OCP\Util::addStyle('files_sharing', 'publicView');
438
-		\OCP\Util::addScript('files_sharing', 'public');
439
-		\OCP\Util::addScript('files_sharing', 'templates');
440
-		\OCP\Util::addScript('files', 'fileactions');
441
-		\OCP\Util::addScript('files', 'fileactionsmenu');
442
-		\OCP\Util::addScript('files', 'jquery.fileupload');
443
-		\OCP\Util::addScript('files_sharing', 'files_drop');
444
-
445
-		if (isset($shareTmpl['folder'])) {
446
-			// JS required for folders
447
-			\OCP\Util::addStyle('files', 'merged');
448
-			\OCP\Util::addScript('files', 'filesummary');
449
-			\OCP\Util::addScript('files', 'templates');
450
-			\OCP\Util::addScript('files', 'breadcrumb');
451
-			\OCP\Util::addScript('files', 'fileinfomodel');
452
-			\OCP\Util::addScript('files', 'newfilemenu');
453
-			\OCP\Util::addScript('files', 'files');
454
-			\OCP\Util::addScript('files', 'filemultiselectmenu');
455
-			\OCP\Util::addScript('files', 'filelist');
456
-			\OCP\Util::addScript('files', 'keyboardshortcuts');
457
-			\OCP\Util::addScript('files', 'operationprogressbar');
458
-
459
-			// Load Viewer scripts
460
-			if (class_exists(LoadViewer::class)) {
461
-				$this->eventDispatcher->dispatch(LoadViewer::class, new LoadViewer());
462
-			}
463
-		}
464
-
465
-		// OpenGraph Support: http://ogp.me/
466
-		\OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
467
-		\OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
468
-		\OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
469
-		\OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
470
-		\OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
471
-		\OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);
472
-
473
-		$event = new GenericEvent(null, ['share' => $share]);
474
-		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts', $event);
475
-
476
-		$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
477
-		$csp->addAllowedFrameDomain('\'self\'');
478
-
479
-		$response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
480
-		$response->setHeaderTitle($shareTmpl['filename']);
481
-		$response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['displayName']]));
482
-
483
-		$isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== \OCP\Constants::PERMISSION_CREATE;
484
-
485
-		if ($isNoneFileDropFolder && !$share->getHideDownload()) {
486
-			\OCP\Util::addScript('files_sharing', 'public_note');
487
-
488
-			$downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
489
-			$downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
490
-			$download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
491
-			$downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
492
-			$directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
493
-			$externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['displayName'], $shareTmpl['filename']);
494
-
495
-			$responseComposer = [];
496
-
497
-			if ($shareIsFolder) {
498
-				$responseComposer[] = $downloadAllWhite;
499
-				$responseComposer[] = $downloadAll;
500
-			} else {
501
-				$responseComposer[] = $downloadWhite;
502
-				$responseComposer[] = $download;
503
-			}
504
-			$responseComposer[] = $directLink;
505
-			if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
506
-				$responseComposer[] = $externalShare;
507
-			}
508
-
509
-			$response->setHeaderActions($responseComposer);
510
-		}
511
-
512
-		$response->setContentSecurityPolicy($csp);
513
-
514
-		$this->emitAccessShareHook($share);
515
-
516
-		return $response;
517
-	}
518
-
519
-	/**
520
-	 * @PublicPage
521
-	 * @NoCSRFRequired
522
-	 *
523
-	 * @param string $token
524
-	 * @param string $files
525
-	 * @param string $path
526
-	 * @param string $downloadStartSecret
527
-	 * @return void|\OCP\AppFramework\Http\Response
528
-	 * @throws NotFoundException
529
-	 */
530
-	public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
531
-		\OC_User::setIncognitoMode(true);
532
-
533
-		$share = $this->shareManager->getShareByToken($token);
534
-
535
-		if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
536
-			return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
537
-		}
538
-
539
-		$files_list = null;
540
-		if (!is_null($files)) { // download selected files
541
-			$files_list = json_decode($files);
542
-			// in case we get only a single file
543
-			if ($files_list === null) {
544
-				$files_list = [$files];
545
-			}
546
-			// Just in case $files is a single int like '1234'
547
-			if (!is_array($files_list)) {
548
-				$files_list = [$files_list];
549
-			}
550
-		}
551
-
552
-		if (!$this->validateShare($share)) {
553
-			throw new NotFoundException();
554
-		}
555
-
556
-		$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
557
-		$originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
558
-
559
-
560
-		// Single file share
561
-		if ($share->getNode() instanceof \OCP\Files\File) {
562
-			// Single file download
563
-			$this->singleFileDownloaded($share, $share->getNode());
564
-		}
565
-		// Directory share
566
-		else {
567
-			/** @var \OCP\Files\Folder $node */
568
-			$node = $share->getNode();
569
-
570
-			// Try to get the path
571
-			if ($path !== '') {
572
-				try {
573
-					$node = $node->get($path);
574
-				} catch (NotFoundException $e) {
575
-					$this->emitAccessShareHook($share, 404, 'Share not found');
576
-					return new NotFoundResponse();
577
-				}
578
-			}
579
-
580
-			$originalSharePath = $userFolder->getRelativePath($node->getPath());
581
-
582
-			if ($node instanceof \OCP\Files\File) {
583
-				// Single file download
584
-				$this->singleFileDownloaded($share, $share->getNode());
585
-			} else {
586
-				try {
587
-					if (!empty($files_list)) {
588
-						$this->fileListDownloaded($share, $files_list, $node);
589
-					} else {
590
-						// The folder is downloaded
591
-						$this->singleFileDownloaded($share, $share->getNode());
592
-					}
593
-				} catch (NotFoundException $e) {
594
-					return new NotFoundResponse();
595
-				}
596
-			}
597
-		}
598
-
599
-		/* FIXME: We should do this all nicely in OCP */
600
-		OC_Util::tearDownFS();
601
-		OC_Util::setupFS($share->getShareOwner());
602
-
603
-		/**
604
-		 * this sets a cookie to be able to recognize the start of the download
605
-		 * the content must not be longer than 32 characters and must only contain
606
-		 * alphanumeric characters
607
-		 */
608
-		if (!empty($downloadStartSecret)
609
-			&& !isset($downloadStartSecret[32])
610
-			&& preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
611
-
612
-			// FIXME: set on the response once we use an actual app framework response
613
-			setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
614
-		}
615
-
616
-		$this->emitAccessShareHook($share);
617
-
618
-		$server_params = [ 'head' => $this->request->getMethod() === 'HEAD' ];
619
-
620
-		/**
621
-		 * Http range requests support
622
-		 */
623
-		if (isset($_SERVER['HTTP_RANGE'])) {
624
-			$server_params['range'] = $this->request->getHeader('Range');
625
-		}
626
-
627
-		// download selected files
628
-		if (!is_null($files) && $files !== '') {
629
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
630
-			// after dispatching the request which results in a "Cannot modify header information" notice.
631
-			OC_Files::get($originalSharePath, $files_list, $server_params);
632
-			exit();
633
-		} else {
634
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
635
-			// after dispatching the request which results in a "Cannot modify header information" notice.
636
-			OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
637
-			exit();
638
-		}
639
-	}
640
-
641
-	/**
642
-	 * create activity for every downloaded file
643
-	 *
644
-	 * @param Share\IShare $share
645
-	 * @param array $files_list
646
-	 * @param \OCP\Files\Folder $node
647
-	 * @throws NotFoundException when trying to download a folder or multiple files of a "hide download" share
648
-	 */
649
-	protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
650
-		if ($share->getHideDownload() && count($files_list) > 1) {
651
-			throw new NotFoundException('Downloading more than 1 file');
652
-		}
653
-
654
-		foreach ($files_list as $file) {
655
-			$subNode = $node->get($file);
656
-			$this->singleFileDownloaded($share, $subNode);
657
-		}
658
-
659
-	}
660
-
661
-	/**
662
-	 * create activity if a single file was downloaded from a link share
663
-	 *
664
-	 * @param Share\IShare $share
665
-	 * @throws NotFoundException when trying to download a folder of a "hide download" share
666
-	 */
667
-	protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
668
-		if ($share->getHideDownload() && $node instanceof Folder) {
669
-			throw new NotFoundException('Downloading a folder');
670
-		}
671
-
672
-		$fileId = $node->getId();
673
-
674
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
675
-		$userNodeList = $userFolder->getById($fileId);
676
-		$userNode = $userNodeList[0];
677
-		$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
678
-		$userPath = $userFolder->getRelativePath($userNode->getPath());
679
-		$ownerPath = $ownerFolder->getRelativePath($node->getPath());
680
-
681
-		$parameters = [$userPath];
682
-
683
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
684
-			if ($node instanceof \OCP\Files\File) {
685
-				$subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
686
-			} else {
687
-				$subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
688
-			}
689
-			$parameters[] = $share->getSharedWith();
690
-		} else {
691
-			if ($node instanceof \OCP\Files\File) {
692
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
693
-			} else {
694
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
695
-			}
696
-		}
697
-
698
-		$this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
699
-
700
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
701
-			$parameters[0] = $ownerPath;
702
-			$this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
703
-		}
704
-	}
705
-
706
-	/**
707
-	 * publish activity
708
-	 *
709
-	 * @param string $subject
710
-	 * @param array $parameters
711
-	 * @param string $affectedUser
712
-	 * @param int $fileId
713
-	 * @param string $filePath
714
-	 */
715
-	protected function publishActivity($subject,
716
-										array $parameters,
717
-										$affectedUser,
718
-										$fileId,
719
-										$filePath) {
720
-
721
-		$event = $this->activityManager->generateEvent();
722
-		$event->setApp('files_sharing')
723
-			->setType('public_links')
724
-			->setSubject($subject, $parameters)
725
-			->setAffectedUser($affectedUser)
726
-			->setObject('files', $fileId, $filePath);
727
-		$this->activityManager->publish($event);
728
-	}
363
+            $freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
364
+            if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
365
+                $freeSpace = max($freeSpace, 0);
366
+            } else {
367
+                $freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
368
+            }
369
+
370
+            $hideFileList = !($share->getPermissions() & \OCP\Constants::PERMISSION_READ);
371
+            $maxUploadFilesize = $freeSpace;
372
+
373
+            $folder = new Template('files', 'list', '');
374
+
375
+            $folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath()));
376
+            $folder->assign('dirToken', $this->getToken());
377
+            $folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
378
+            $folder->assign('isPublic', true);
379
+            $folder->assign('hideFileList', $hideFileList);
380
+            $folder->assign('publicUploadEnabled', 'no');
381
+            // default to list view
382
+            $folder->assign('showgridview', false);
383
+            $folder->assign('uploadMaxFilesize', $maxUploadFilesize);
384
+            $folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
385
+            $folder->assign('freeSpace', $freeSpace);
386
+            $folder->assign('usedSpacePercent', 0);
387
+            $folder->assign('trash', false);
388
+            $shareTmpl['folder'] = $folder->fetchPage();
389
+        } else {
390
+            $shareIsFolder = false;
391
+        }
392
+
393
+        // default to list view
394
+        $shareTmpl['showgridview'] = false;
395
+
396
+        $shareTmpl['hideFileList'] = $hideFileList;
397
+        $shareTmpl['shareOwner'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
398
+        $shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', ['token' => $this->getToken()]);
399
+        $shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $this->getToken()]);
400
+        $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
401
+        $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
402
+        $shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
403
+        $shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
404
+        $shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
405
+        $shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
406
+
407
+        if ($shareTmpl['previewSupported']) {
408
+            $shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute( 'files_sharing.PublicPreview.getPreview',
409
+                ['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
410
+            $ogPreview = $shareTmpl['previewImage'];
411
+
412
+            // We just have direct previews for image files
413
+            if ($shareNode->getMimePart() === 'image') {
414
+                $shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]);
415
+
416
+                $ogPreview = $shareTmpl['previewURL'];
417
+
418
+                //Whatapp is kind of picky about their size requirements
419
+                if ($this->request->isUserAgent(['/^WhatsApp/'])) {
420
+                    $ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
421
+                        'token' => $this->getToken(),
422
+                        'x' => 256,
423
+                        'y' => 256,
424
+                        'a' => true,
425
+                    ]);
426
+                }
427
+            }
428
+        } else {
429
+            $shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
430
+            $ogPreview = $shareTmpl['previewImage'];
431
+        }
432
+
433
+        // Load files we need
434
+        \OCP\Util::addScript('files', 'semaphore');
435
+        \OCP\Util::addScript('files', 'file-upload');
436
+        \OCP\Util::addStyle('files_sharing', 'publicView');
437
+        \OCP\Util::addScript('files_sharing', 'public');
438
+        \OCP\Util::addScript('files_sharing', 'templates');
439
+        \OCP\Util::addScript('files', 'fileactions');
440
+        \OCP\Util::addScript('files', 'fileactionsmenu');
441
+        \OCP\Util::addScript('files', 'jquery.fileupload');
442
+        \OCP\Util::addScript('files_sharing', 'files_drop');
443
+
444
+        if (isset($shareTmpl['folder'])) {
445
+            // JS required for folders
446
+            \OCP\Util::addStyle('files', 'merged');
447
+            \OCP\Util::addScript('files', 'filesummary');
448
+            \OCP\Util::addScript('files', 'templates');
449
+            \OCP\Util::addScript('files', 'breadcrumb');
450
+            \OCP\Util::addScript('files', 'fileinfomodel');
451
+            \OCP\Util::addScript('files', 'newfilemenu');
452
+            \OCP\Util::addScript('files', 'files');
453
+            \OCP\Util::addScript('files', 'filemultiselectmenu');
454
+            \OCP\Util::addScript('files', 'filelist');
455
+            \OCP\Util::addScript('files', 'keyboardshortcuts');
456
+            \OCP\Util::addScript('files', 'operationprogressbar');
457
+
458
+            // Load Viewer scripts
459
+            if (class_exists(LoadViewer::class)) {
460
+                $this->eventDispatcher->dispatch(LoadViewer::class, new LoadViewer());
461
+            }
462
+        }
463
+
464
+        // OpenGraph Support: http://ogp.me/
465
+        \OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
466
+        \OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
467
+        \OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
468
+        \OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
469
+        \OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
470
+        \OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);
471
+
472
+        $event = new GenericEvent(null, ['share' => $share]);
473
+        $this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts', $event);
474
+
475
+        $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
476
+        $csp->addAllowedFrameDomain('\'self\'');
477
+
478
+        $response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
479
+        $response->setHeaderTitle($shareTmpl['filename']);
480
+        $response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['displayName']]));
481
+
482
+        $isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== \OCP\Constants::PERMISSION_CREATE;
483
+
484
+        if ($isNoneFileDropFolder && !$share->getHideDownload()) {
485
+            \OCP\Util::addScript('files_sharing', 'public_note');
486
+
487
+            $downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
488
+            $downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
489
+            $download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
490
+            $downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
491
+            $directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
492
+            $externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['displayName'], $shareTmpl['filename']);
493
+
494
+            $responseComposer = [];
495
+
496
+            if ($shareIsFolder) {
497
+                $responseComposer[] = $downloadAllWhite;
498
+                $responseComposer[] = $downloadAll;
499
+            } else {
500
+                $responseComposer[] = $downloadWhite;
501
+                $responseComposer[] = $download;
502
+            }
503
+            $responseComposer[] = $directLink;
504
+            if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
505
+                $responseComposer[] = $externalShare;
506
+            }
507
+
508
+            $response->setHeaderActions($responseComposer);
509
+        }
510
+
511
+        $response->setContentSecurityPolicy($csp);
512
+
513
+        $this->emitAccessShareHook($share);
514
+
515
+        return $response;
516
+    }
517
+
518
+    /**
519
+     * @PublicPage
520
+     * @NoCSRFRequired
521
+     *
522
+     * @param string $token
523
+     * @param string $files
524
+     * @param string $path
525
+     * @param string $downloadStartSecret
526
+     * @return void|\OCP\AppFramework\Http\Response
527
+     * @throws NotFoundException
528
+     */
529
+    public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
530
+        \OC_User::setIncognitoMode(true);
531
+
532
+        $share = $this->shareManager->getShareByToken($token);
533
+
534
+        if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
535
+            return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
536
+        }
537
+
538
+        $files_list = null;
539
+        if (!is_null($files)) { // download selected files
540
+            $files_list = json_decode($files);
541
+            // in case we get only a single file
542
+            if ($files_list === null) {
543
+                $files_list = [$files];
544
+            }
545
+            // Just in case $files is a single int like '1234'
546
+            if (!is_array($files_list)) {
547
+                $files_list = [$files_list];
548
+            }
549
+        }
550
+
551
+        if (!$this->validateShare($share)) {
552
+            throw new NotFoundException();
553
+        }
554
+
555
+        $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
556
+        $originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
557
+
558
+
559
+        // Single file share
560
+        if ($share->getNode() instanceof \OCP\Files\File) {
561
+            // Single file download
562
+            $this->singleFileDownloaded($share, $share->getNode());
563
+        }
564
+        // Directory share
565
+        else {
566
+            /** @var \OCP\Files\Folder $node */
567
+            $node = $share->getNode();
568
+
569
+            // Try to get the path
570
+            if ($path !== '') {
571
+                try {
572
+                    $node = $node->get($path);
573
+                } catch (NotFoundException $e) {
574
+                    $this->emitAccessShareHook($share, 404, 'Share not found');
575
+                    return new NotFoundResponse();
576
+                }
577
+            }
578
+
579
+            $originalSharePath = $userFolder->getRelativePath($node->getPath());
580
+
581
+            if ($node instanceof \OCP\Files\File) {
582
+                // Single file download
583
+                $this->singleFileDownloaded($share, $share->getNode());
584
+            } else {
585
+                try {
586
+                    if (!empty($files_list)) {
587
+                        $this->fileListDownloaded($share, $files_list, $node);
588
+                    } else {
589
+                        // The folder is downloaded
590
+                        $this->singleFileDownloaded($share, $share->getNode());
591
+                    }
592
+                } catch (NotFoundException $e) {
593
+                    return new NotFoundResponse();
594
+                }
595
+            }
596
+        }
597
+
598
+        /* FIXME: We should do this all nicely in OCP */
599
+        OC_Util::tearDownFS();
600
+        OC_Util::setupFS($share->getShareOwner());
601
+
602
+        /**
603
+         * this sets a cookie to be able to recognize the start of the download
604
+         * the content must not be longer than 32 characters and must only contain
605
+         * alphanumeric characters
606
+         */
607
+        if (!empty($downloadStartSecret)
608
+            && !isset($downloadStartSecret[32])
609
+            && preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
610
+
611
+            // FIXME: set on the response once we use an actual app framework response
612
+            setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
613
+        }
614
+
615
+        $this->emitAccessShareHook($share);
616
+
617
+        $server_params = [ 'head' => $this->request->getMethod() === 'HEAD' ];
618
+
619
+        /**
620
+         * Http range requests support
621
+         */
622
+        if (isset($_SERVER['HTTP_RANGE'])) {
623
+            $server_params['range'] = $this->request->getHeader('Range');
624
+        }
625
+
626
+        // download selected files
627
+        if (!is_null($files) && $files !== '') {
628
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
629
+            // after dispatching the request which results in a "Cannot modify header information" notice.
630
+            OC_Files::get($originalSharePath, $files_list, $server_params);
631
+            exit();
632
+        } else {
633
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
634
+            // after dispatching the request which results in a "Cannot modify header information" notice.
635
+            OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
636
+            exit();
637
+        }
638
+    }
639
+
640
+    /**
641
+     * create activity for every downloaded file
642
+     *
643
+     * @param Share\IShare $share
644
+     * @param array $files_list
645
+     * @param \OCP\Files\Folder $node
646
+     * @throws NotFoundException when trying to download a folder or multiple files of a "hide download" share
647
+     */
648
+    protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
649
+        if ($share->getHideDownload() && count($files_list) > 1) {
650
+            throw new NotFoundException('Downloading more than 1 file');
651
+        }
652
+
653
+        foreach ($files_list as $file) {
654
+            $subNode = $node->get($file);
655
+            $this->singleFileDownloaded($share, $subNode);
656
+        }
657
+
658
+    }
659
+
660
+    /**
661
+     * create activity if a single file was downloaded from a link share
662
+     *
663
+     * @param Share\IShare $share
664
+     * @throws NotFoundException when trying to download a folder of a "hide download" share
665
+     */
666
+    protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
667
+        if ($share->getHideDownload() && $node instanceof Folder) {
668
+            throw new NotFoundException('Downloading a folder');
669
+        }
670
+
671
+        $fileId = $node->getId();
672
+
673
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
674
+        $userNodeList = $userFolder->getById($fileId);
675
+        $userNode = $userNodeList[0];
676
+        $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
677
+        $userPath = $userFolder->getRelativePath($userNode->getPath());
678
+        $ownerPath = $ownerFolder->getRelativePath($node->getPath());
679
+
680
+        $parameters = [$userPath];
681
+
682
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
683
+            if ($node instanceof \OCP\Files\File) {
684
+                $subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
685
+            } else {
686
+                $subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
687
+            }
688
+            $parameters[] = $share->getSharedWith();
689
+        } else {
690
+            if ($node instanceof \OCP\Files\File) {
691
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
692
+            } else {
693
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
694
+            }
695
+        }
696
+
697
+        $this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
698
+
699
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
700
+            $parameters[0] = $ownerPath;
701
+            $this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
702
+        }
703
+    }
704
+
705
+    /**
706
+     * publish activity
707
+     *
708
+     * @param string $subject
709
+     * @param array $parameters
710
+     * @param string $affectedUser
711
+     * @param int $fileId
712
+     * @param string $filePath
713
+     */
714
+    protected function publishActivity($subject,
715
+                                        array $parameters,
716
+                                        $affectedUser,
717
+                                        $fileId,
718
+                                        $filePath) {
719
+
720
+        $event = $this->activityManager->generateEvent();
721
+        $event->setApp('files_sharing')
722
+            ->setType('public_links')
723
+            ->setSubject($subject, $parameters)
724
+            ->setAffectedUser($affectedUser)
725
+            ->setObject('files', $fileId, $filePath);
726
+        $this->activityManager->publish($event);
727
+    }
729 728
 
730 729
 
731 730
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -221,7 +221,7 @@  discard block
 block discarded – undo
221 221
 
222 222
 	protected function authSucceeded() {
223 223
 		// For share this was always set so it is still used in other apps
224
-		$this->session->set('public_link_authenticated', (string)$this->share->getId());
224
+		$this->session->set('public_link_authenticated', (string) $this->share->getId());
225 225
 	}
226 226
 
227 227
 	protected function authFailed() {
@@ -242,7 +242,7 @@  discard block
 block discarded – undo
242 242
 		$itemType = $itemSource = $uidOwner = '';
243 243
 		$token = $share;
244 244
 		$exception = null;
245
-		if($share instanceof \OCP\Share\IShare) {
245
+		if ($share instanceof \OCP\Share\IShare) {
246 246
 			try {
247 247
 				$token = $share->getToken();
248 248
 				$uidOwner = $share->getSharedBy();
@@ -261,7 +261,7 @@  discard block
 block discarded – undo
261 261
 			'errorCode' => $errorCode,
262 262
 			'errorMessage' => $errorMessage,
263 263
 		]);
264
-		if(!is_null($exception)) {
264
+		if (!is_null($exception)) {
265 265
 			throw $exception;
266 266
 		}
267 267
 	}
@@ -406,7 +406,7 @@  discard block
 block discarded – undo
406 406
 		$shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
407 407
 
408 408
 		if ($shareTmpl['previewSupported']) {
409
-			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute( 'files_sharing.PublicPreview.getPreview',
409
+			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview',
410 410
 				['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
411 411
 			$ogPreview = $shareTmpl['previewImage'];
412 412
 
@@ -464,7 +464,7 @@  discard block
 block discarded – undo
464 464
 
465 465
 		// OpenGraph Support: http://ogp.me/
466 466
 		\OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
467
-		\OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
467
+		\OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName().($this->defaults->getSlogan() !== '' ? ' - '.$this->defaults->getSlogan() : '')]);
468 468
 		\OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
469 469
 		\OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
470 470
 		\OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
@@ -532,7 +532,7 @@  discard block
 block discarded – undo
532 532
 
533 533
 		$share = $this->shareManager->getShareByToken($token);
534 534
 
535
-		if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
535
+		if (!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
536 536
 			return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
537 537
 		}
538 538
 
@@ -615,7 +615,7 @@  discard block
 block discarded – undo
615 615
 
616 616
 		$this->emitAccessShareHook($share);
617 617
 
618
-		$server_params = [ 'head' => $this->request->getMethod() === 'HEAD' ];
618
+		$server_params = ['head' => $this->request->getMethod() === 'HEAD'];
619 619
 
620 620
 		/**
621 621
 		 * Http range requests support
Please login to merge, or discard this patch.
apps/user_ldap/ajax/deleteConfiguration.php 1 patch
Indentation   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -33,8 +33,8 @@
 block discarded – undo
33 33
 $prefix = (string)$_POST['ldap_serverconfig_chooser'];
34 34
 $helper = new \OCA\User_LDAP\Helper(\OC::$server->getConfig());
35 35
 if($helper->deleteServerConfiguration($prefix)) {
36
-	\OC_JSON::success();
36
+    \OC_JSON::success();
37 37
 } else {
38
-	$l = \OC::$server->getL10N('user_ldap');
39
-	\OC_JSON::error(['message' => $l->t('Failed to delete the server configuration')]);
38
+    $l = \OC::$server->getL10N('user_ldap');
39
+    \OC_JSON::error(['message' => $l->t('Failed to delete the server configuration')]);
40 40
 }
Please login to merge, or discard this patch.
apps/user_ldap/ajax/wizard.php 2 patches
Indentation   +85 added lines, -85 removed lines patch added patch discarded remove patch
@@ -36,13 +36,13 @@  discard block
 block discarded – undo
36 36
 $l = \OC::$server->getL10N('user_ldap');
37 37
 
38 38
 if(!isset($_POST['action'])) {
39
-	\OC_JSON::error(['message' => $l->t('No action specified')]);
39
+    \OC_JSON::error(['message' => $l->t('No action specified')]);
40 40
 }
41 41
 $action = (string)$_POST['action'];
42 42
 
43 43
 
44 44
 if(!isset($_POST['ldap_serverconfig_chooser'])) {
45
-	\OC_JSON::error(['message' => $l->t('No configuration specified')]);
45
+    \OC_JSON::error(['message' => $l->t('No configuration specified')]);
46 46
 }
47 47
 $prefix = (string)$_POST['ldap_serverconfig_chooser'];
48 48
 
@@ -55,96 +55,96 @@  discard block
 block discarded – undo
55 55
 $con->setIgnoreValidation(true);
56 56
 
57 57
 $userManager = new \OCA\User_LDAP\User\Manager(
58
-	\OC::$server->getConfig(),
59
-	new \OCA\User_LDAP\FilesystemHelper(),
60
-	new \OCA\User_LDAP\LogWrapper(),
61
-	\OC::$server->getAvatarManager(),
62
-	new \OCP\Image(),
63
-	\OC::$server->getDatabaseConnection(),
64
-	\OC::$server->getUserManager(),
65
-	\OC::$server->getNotificationManager());
58
+    \OC::$server->getConfig(),
59
+    new \OCA\User_LDAP\FilesystemHelper(),
60
+    new \OCA\User_LDAP\LogWrapper(),
61
+    \OC::$server->getAvatarManager(),
62
+    new \OCP\Image(),
63
+    \OC::$server->getDatabaseConnection(),
64
+    \OC::$server->getUserManager(),
65
+    \OC::$server->getNotificationManager());
66 66
 
67 67
 $access = new \OCA\User_LDAP\Access(
68
-	$con,
69
-	$ldapWrapper,
70
-	$userManager,
71
-	new \OCA\User_LDAP\Helper(\OC::$server->getConfig()),
72
-	\OC::$server->getConfig(),
73
-	\OC::$server->getUserManager()
68
+    $con,
69
+    $ldapWrapper,
70
+    $userManager,
71
+    new \OCA\User_LDAP\Helper(\OC::$server->getConfig()),
72
+    \OC::$server->getConfig(),
73
+    \OC::$server->getUserManager()
74 74
 );
75 75
 
76 76
 $wizard = new \OCA\User_LDAP\Wizard($configuration, $ldapWrapper, $access);
77 77
 
78 78
 switch($action) {
79
-	case 'guessPortAndTLS':
80
-	case 'guessBaseDN':
81
-	case 'detectEmailAttribute':
82
-	case 'detectUserDisplayNameAttribute':
83
-	case 'determineGroupMemberAssoc':
84
-	case 'determineUserObjectClasses':
85
-	case 'determineGroupObjectClasses':
86
-	case 'determineGroupsForUsers':
87
-	case 'determineGroupsForGroups':
88
-	case 'determineAttributes':
89
-	case 'getUserListFilter':
90
-	case 'getUserLoginFilter':
91
-	case 'getGroupFilter':
92
-	case 'countUsers':
93
-	case 'countGroups':
94
-	case 'countInBaseDN':
95
-		try {
96
-			$result = $wizard->$action();
97
-			if($result !== false) {
98
-				\OC_JSON::success($result->getResultArray());
99
-				exit;
100
-			}
101
-		} catch (\Exception $e) {
102
-			\OC_JSON::error(['message' => $e->getMessage(), 'code' => $e->getCode()]);
103
-			exit;
104
-		}
105
-		\OC_JSON::error();
106
-		exit;
107
-		break;
79
+    case 'guessPortAndTLS':
80
+    case 'guessBaseDN':
81
+    case 'detectEmailAttribute':
82
+    case 'detectUserDisplayNameAttribute':
83
+    case 'determineGroupMemberAssoc':
84
+    case 'determineUserObjectClasses':
85
+    case 'determineGroupObjectClasses':
86
+    case 'determineGroupsForUsers':
87
+    case 'determineGroupsForGroups':
88
+    case 'determineAttributes':
89
+    case 'getUserListFilter':
90
+    case 'getUserLoginFilter':
91
+    case 'getGroupFilter':
92
+    case 'countUsers':
93
+    case 'countGroups':
94
+    case 'countInBaseDN':
95
+        try {
96
+            $result = $wizard->$action();
97
+            if($result !== false) {
98
+                \OC_JSON::success($result->getResultArray());
99
+                exit;
100
+            }
101
+        } catch (\Exception $e) {
102
+            \OC_JSON::error(['message' => $e->getMessage(), 'code' => $e->getCode()]);
103
+            exit;
104
+        }
105
+        \OC_JSON::error();
106
+        exit;
107
+        break;
108 108
 
109
-	case 'testLoginName': {
110
-		try {
111
-			$loginName = $_POST['ldap_test_loginname'];
112
-			$result = $wizard->$action($loginName);
113
-			if($result !== false) {
114
-				\OC_JSON::success($result->getResultArray());
115
-				exit;
116
-			}
117
-		} catch (\Exception $e) {
118
-			\OC_JSON::error(['message' => $e->getMessage()]);
119
-			exit;
120
-		}
121
-		\OC_JSON::error();
122
-		exit;
123
-		break;
124
-	}
109
+    case 'testLoginName': {
110
+        try {
111
+            $loginName = $_POST['ldap_test_loginname'];
112
+            $result = $wizard->$action($loginName);
113
+            if($result !== false) {
114
+                \OC_JSON::success($result->getResultArray());
115
+                exit;
116
+            }
117
+        } catch (\Exception $e) {
118
+            \OC_JSON::error(['message' => $e->getMessage()]);
119
+            exit;
120
+        }
121
+        \OC_JSON::error();
122
+        exit;
123
+        break;
124
+    }
125 125
 
126
-	case 'save':
127
-		$key = isset($_POST['cfgkey']) ? $_POST['cfgkey'] : false;
128
-		$val = isset($_POST['cfgval']) ? $_POST['cfgval'] : null;
129
-		if($key === false || is_null($val)) {
130
-			\OC_JSON::error(['message' => $l->t('No data specified')]);
131
-			exit;
132
-		}
133
-		$cfg = [$key => $val];
134
-		$setParameters = [];
135
-		$configuration->setConfiguration($cfg, $setParameters);
136
-		if(!in_array($key, $setParameters)) {
137
-			\OC_JSON::error(['message' => $l->t($key.
138
-				' Could not set configuration %s', $setParameters[0])]);
139
-			exit;
140
-		}
141
-		$configuration->saveConfiguration();
142
-		//clear the cache on save
143
-		$connection = new \OCA\User_LDAP\Connection($ldapWrapper, $prefix);
144
-		$connection->clearCache();
145
-		\OC_JSON::success();
146
-		break;
147
-	default:
148
-		\OC_JSON::error(['message' => $l->t('Action does not exist')]);
149
-		break;
126
+    case 'save':
127
+        $key = isset($_POST['cfgkey']) ? $_POST['cfgkey'] : false;
128
+        $val = isset($_POST['cfgval']) ? $_POST['cfgval'] : null;
129
+        if($key === false || is_null($val)) {
130
+            \OC_JSON::error(['message' => $l->t('No data specified')]);
131
+            exit;
132
+        }
133
+        $cfg = [$key => $val];
134
+        $setParameters = [];
135
+        $configuration->setConfiguration($cfg, $setParameters);
136
+        if(!in_array($key, $setParameters)) {
137
+            \OC_JSON::error(['message' => $l->t($key.
138
+                ' Could not set configuration %s', $setParameters[0])]);
139
+            exit;
140
+        }
141
+        $configuration->saveConfiguration();
142
+        //clear the cache on save
143
+        $connection = new \OCA\User_LDAP\Connection($ldapWrapper, $prefix);
144
+        $connection->clearCache();
145
+        \OC_JSON::success();
146
+        break;
147
+    default:
148
+        \OC_JSON::error(['message' => $l->t('Action does not exist')]);
149
+        break;
150 150
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -35,16 +35,16 @@  discard block
 block discarded – undo
35 35
 
36 36
 $l = \OC::$server->getL10N('user_ldap');
37 37
 
38
-if(!isset($_POST['action'])) {
38
+if (!isset($_POST['action'])) {
39 39
 	\OC_JSON::error(['message' => $l->t('No action specified')]);
40 40
 }
41
-$action = (string)$_POST['action'];
41
+$action = (string) $_POST['action'];
42 42
 
43 43
 
44
-if(!isset($_POST['ldap_serverconfig_chooser'])) {
44
+if (!isset($_POST['ldap_serverconfig_chooser'])) {
45 45
 	\OC_JSON::error(['message' => $l->t('No configuration specified')]);
46 46
 }
47
-$prefix = (string)$_POST['ldap_serverconfig_chooser'];
47
+$prefix = (string) $_POST['ldap_serverconfig_chooser'];
48 48
 
49 49
 $ldapWrapper = new \OCA\User_LDAP\LDAP();
50 50
 $configuration = new \OCA\User_LDAP\Configuration($prefix);
@@ -75,7 +75,7 @@  discard block
 block discarded – undo
75 75
 
76 76
 $wizard = new \OCA\User_LDAP\Wizard($configuration, $ldapWrapper, $access);
77 77
 
78
-switch($action) {
78
+switch ($action) {
79 79
 	case 'guessPortAndTLS':
80 80
 	case 'guessBaseDN':
81 81
 	case 'detectEmailAttribute':
@@ -94,7 +94,7 @@  discard block
 block discarded – undo
94 94
 	case 'countInBaseDN':
95 95
 		try {
96 96
 			$result = $wizard->$action();
97
-			if($result !== false) {
97
+			if ($result !== false) {
98 98
 				\OC_JSON::success($result->getResultArray());
99 99
 				exit;
100 100
 			}
@@ -110,7 +110,7 @@  discard block
 block discarded – undo
110 110
 		try {
111 111
 			$loginName = $_POST['ldap_test_loginname'];
112 112
 			$result = $wizard->$action($loginName);
113
-			if($result !== false) {
113
+			if ($result !== false) {
114 114
 				\OC_JSON::success($result->getResultArray());
115 115
 				exit;
116 116
 			}
@@ -126,14 +126,14 @@  discard block
 block discarded – undo
126 126
 	case 'save':
127 127
 		$key = isset($_POST['cfgkey']) ? $_POST['cfgkey'] : false;
128 128
 		$val = isset($_POST['cfgval']) ? $_POST['cfgval'] : null;
129
-		if($key === false || is_null($val)) {
129
+		if ($key === false || is_null($val)) {
130 130
 			\OC_JSON::error(['message' => $l->t('No data specified')]);
131 131
 			exit;
132 132
 		}
133 133
 		$cfg = [$key => $val];
134 134
 		$setParameters = [];
135 135
 		$configuration->setConfiguration($cfg, $setParameters);
136
-		if(!in_array($key, $setParameters)) {
136
+		if (!in_array($key, $setParameters)) {
137 137
 			\OC_JSON::error(['message' => $l->t($key.
138 138
 				' Could not set configuration %s', $setParameters[0])]);
139 139
 			exit;
Please login to merge, or discard this patch.
apps/user_ldap/ajax/getConfiguration.php 1 patch
Indentation   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -35,7 +35,7 @@
 block discarded – undo
35 35
 $connection = new \OCA\User_LDAP\Connection($ldapWrapper, $prefix);
36 36
 $configuration = $connection->getConfiguration();
37 37
 if (isset($configuration['ldap_agent_password']) && $configuration['ldap_agent_password'] !== '') {
38
-	// hide password
39
-	$configuration['ldap_agent_password'] = '**PASSWORD SET**';
38
+    // hide password
39
+    $configuration['ldap_agent_password'] = '**PASSWORD SET**';
40 40
 }
41 41
 \OC_JSON::success(['configuration' => $configuration]);
Please login to merge, or discard this patch.
apps/user_ldap/ajax/testConfiguration.php 2 patches
Indentation   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -39,24 +39,24 @@  discard block
 block discarded – undo
39 39
 
40 40
 
41 41
 try {
42
-	$configurationOk = true;
43
-	$conf = $connection->getConfiguration();
44
-	if ($conf['ldap_configuration_active'] === '0') {
45
-		//needs to be true, otherwise it will also fail with an irritating message
46
-		$conf['ldap_configuration_active'] = '1';
47
-		$configurationOk = $connection->setConfiguration($conf);
48
-	}
49
-	if ($configurationOk) {
50
-		//Configuration is okay
51
-		/*
42
+    $configurationOk = true;
43
+    $conf = $connection->getConfiguration();
44
+    if ($conf['ldap_configuration_active'] === '0') {
45
+        //needs to be true, otherwise it will also fail with an irritating message
46
+        $conf['ldap_configuration_active'] = '1';
47
+        $configurationOk = $connection->setConfiguration($conf);
48
+    }
49
+    if ($configurationOk) {
50
+        //Configuration is okay
51
+        /*
52 52
 		 * Clossing the session since it won't be used from this point on. There might be a potential
53 53
 		 * race condition if a second request is made: either this request or the other might not
54 54
 		 * contact the LDAP backup server the first time when it should, but there shouldn't be any
55 55
 		 * problem with that other than the extra connection.
56 56
 		 */
57
-		\OC::$server->getSession()->close();
58
-		if ($connection->bind()) {
59
-			/*
57
+        \OC::$server->getSession()->close();
58
+        if ($connection->bind()) {
59
+            /*
60 60
 			 * This shiny if block is an ugly hack to find out whether anonymous
61 61
 			 * bind is possible on AD or not. Because AD happily and constantly
62 62
 			 * replies with success to any anonymous bind request, we need to
@@ -65,24 +65,24 @@  discard block
 block discarded – undo
65 65
 			 * exception by the LDAP wrapper. We catch this. Other cases may
66 66
 			 * pass (like e.g. expected syntax error).
67 67
 			 */
68
-			try {
69
-				$ldapWrapper->read($connection->getConnectionResource(), '', 'objectClass=*', ['dn']);
70
-			} catch (\Exception $e) {
71
-				if($e->getCode() === 1) {
72
-					\OC_JSON::error(['message' => $l->t('Invalid configuration: Anonymous binding is not allowed.')]);
73
-					exit;
74
-				}
75
-			}
76
-			\OC_JSON::success(['message'
77
-			=> $l->t('Valid configuration, connection established!')]);
78
-		} else {
79
-			\OC_JSON::error(['message'
80
-			=> $l->t('Valid configuration, but binding failed. Please check the server settings and credentials.')]);
81
-		}
82
-	} else {
83
-		\OC_JSON::error(['message'
84
-		=> $l->t('Invalid configuration. Please have a look at the logs for further details.')]);
85
-	}
68
+            try {
69
+                $ldapWrapper->read($connection->getConnectionResource(), '', 'objectClass=*', ['dn']);
70
+            } catch (\Exception $e) {
71
+                if($e->getCode() === 1) {
72
+                    \OC_JSON::error(['message' => $l->t('Invalid configuration: Anonymous binding is not allowed.')]);
73
+                    exit;
74
+                }
75
+            }
76
+            \OC_JSON::success(['message'
77
+            => $l->t('Valid configuration, connection established!')]);
78
+        } else {
79
+            \OC_JSON::error(['message'
80
+            => $l->t('Valid configuration, but binding failed. Please check the server settings and credentials.')]);
81
+        }
82
+    } else {
83
+        \OC_JSON::error(['message'
84
+        => $l->t('Invalid configuration. Please have a look at the logs for further details.')]);
85
+    }
86 86
 } catch (\Exception $e) {
87
-	\OC_JSON::error(['message' => $e->getMessage()]);
87
+    \OC_JSON::error(['message' => $e->getMessage()]);
88 88
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -68,7 +68,7 @@
 block discarded – undo
68 68
 			try {
69 69
 				$ldapWrapper->read($connection->getConnectionResource(), '', 'objectClass=*', ['dn']);
70 70
 			} catch (\Exception $e) {
71
-				if($e->getCode() === 1) {
71
+				if ($e->getCode() === 1) {
72 72
 					\OC_JSON::error(['message' => $l->t('Invalid configuration: Anonymous binding is not allowed.')]);
73 73
 					exit;
74 74
 				}
Please login to merge, or discard this patch.