Passed
Push — master ( f7ea09...bc6053 )
by Joas
14:25
created
apps/files_sharing/lib/Controller/ShareAPIController.php 1 patch
Indentation   +1164 added lines, -1164 removed lines patch added patch discarded remove patch
@@ -65,1175 +65,1175 @@
 block discarded – undo
65 65
  */
66 66
 class ShareAPIController extends OCSController {
67 67
 
68
-	/** @var IManager */
69
-	private $shareManager;
70
-	/** @var IGroupManager */
71
-	private $groupManager;
72
-	/** @var IUserManager */
73
-	private $userManager;
74
-	/** @var IRootFolder */
75
-	private $rootFolder;
76
-	/** @var IURLGenerator */
77
-	private $urlGenerator;
78
-	/** @var string */
79
-	private $currentUser;
80
-	/** @var IL10N */
81
-	private $l;
82
-	/** @var \OCP\Files\Node */
83
-	private $lockedNode;
84
-	/** @var IConfig */
85
-	private $config;
86
-	/** @var IAppManager */
87
-	private $appManager;
88
-	/** @var IServerContainer */
89
-	private $serverContainer;
90
-
91
-	/**
92
-	 * Share20OCS constructor.
93
-	 *
94
-	 * @param string $appName
95
-	 * @param IRequest $request
96
-	 * @param IManager $shareManager
97
-	 * @param IGroupManager $groupManager
98
-	 * @param IUserManager $userManager
99
-	 * @param IRootFolder $rootFolder
100
-	 * @param IURLGenerator $urlGenerator
101
-	 * @param string $userId
102
-	 * @param IL10N $l10n
103
-	 * @param IConfig $config
104
-	 * @param IAppManager $appManager
105
-	 * @param IServerContainer $serverContainer
106
-	 */
107
-	public function __construct(
108
-		string $appName,
109
-		IRequest $request,
110
-		IManager $shareManager,
111
-		IGroupManager $groupManager,
112
-		IUserManager $userManager,
113
-		IRootFolder $rootFolder,
114
-		IURLGenerator $urlGenerator,
115
-		string $userId = null,
116
-		IL10N $l10n,
117
-		IConfig $config,
118
-		IAppManager $appManager,
119
-		IServerContainer $serverContainer
120
-	) {
121
-		parent::__construct($appName, $request);
122
-
123
-		$this->shareManager = $shareManager;
124
-		$this->userManager = $userManager;
125
-		$this->groupManager = $groupManager;
126
-		$this->request = $request;
127
-		$this->rootFolder = $rootFolder;
128
-		$this->urlGenerator = $urlGenerator;
129
-		$this->currentUser = $userId;
130
-		$this->l = $l10n;
131
-		$this->config = $config;
132
-		$this->appManager = $appManager;
133
-		$this->serverContainer = $serverContainer;
134
-	}
135
-
136
-	/**
137
-	 * Convert an IShare to an array for OCS output
138
-	 *
139
-	 * @param \OCP\Share\IShare $share
140
-	 * @param Node|null $recipientNode
141
-	 * @return array
142
-	 * @throws NotFoundException In case the node can't be resolved.
143
-	 *
144
-	 * @suppress PhanUndeclaredClassMethod
145
-	 */
146
-	protected function formatShare(\OCP\Share\IShare $share, Node $recipientNode = null): array {
147
-		$sharedBy = $this->userManager->get($share->getSharedBy());
148
-		$shareOwner = $this->userManager->get($share->getShareOwner());
149
-
150
-		$result = [
151
-			'id' => $share->getId(),
152
-			'share_type' => $share->getShareType(),
153
-			'uid_owner' => $share->getSharedBy(),
154
-			'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(),
155
-			'permissions' => $share->getPermissions(),
156
-			'stime' => $share->getShareTime()->getTimestamp(),
157
-			'parent' => null,
158
-			'expiration' => null,
159
-			'token' => null,
160
-			'uid_file_owner' => $share->getShareOwner(),
161
-			'note' => $share->getNote(),
162
-			'label' => $share->getLabel(),
163
-			'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(),
164
-		];
165
-
166
-		$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
167
-		if ($recipientNode) {
168
-			$node = $recipientNode;
169
-		} else {
170
-			$nodes = $userFolder->getById($share->getNodeId());
171
-			if (empty($nodes)) {
172
-				// fallback to guessing the path
173
-				$node = $userFolder->get($share->getTarget());
174
-				if ($node === null || $share->getTarget() === '') {
175
-					throw new NotFoundException();
176
-				}
177
-			} else {
178
-				$node = $nodes[0];
179
-			}
180
-		}
181
-
182
-		$result['path'] = $userFolder->getRelativePath($node->getPath());
183
-		if ($node instanceOf \OCP\Files\Folder) {
184
-			$result['item_type'] = 'folder';
185
-		} else {
186
-			$result['item_type'] = 'file';
187
-		}
188
-		$result['mimetype'] = $node->getMimetype();
189
-		$result['storage_id'] = $node->getStorage()->getId();
190
-		$result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
191
-		$result['item_source'] = $node->getId();
192
-		$result['file_source'] = $node->getId();
193
-		$result['file_parent'] = $node->getParent()->getId();
194
-		$result['file_target'] = $share->getTarget();
195
-
196
-		$expiration = $share->getExpirationDate();
197
-		if ($expiration !== null) {
198
-			$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
199
-		}
200
-
201
-		if ($share->getShareType() === Share::SHARE_TYPE_USER) {
202
-			$sharedWith = $this->userManager->get($share->getSharedWith());
203
-			$result['share_with'] = $share->getSharedWith();
204
-			$result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith();
205
-		} else if ($share->getShareType() === Share::SHARE_TYPE_GROUP) {
206
-			$group = $this->groupManager->get($share->getSharedWith());
207
-			$result['share_with'] = $share->getSharedWith();
208
-			$result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
209
-		} else if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
210
-
211
-			// "share_with" and "share_with_displayname" for passwords of link
212
-			// shares was deprecated in Nextcloud 15, use "password" instead.
213
-			$result['share_with'] = $share->getPassword();
214
-			$result['share_with_displayname'] = $share->getPassword();
215
-
216
-			$result['password'] = $share->getPassword();
217
-
218
-			$result['send_password_by_talk'] = $share->getSendPasswordByTalk();
219
-
220
-			$result['token'] = $share->getToken();
221
-			$result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
222
-
223
-		} else if ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() === Share::SHARE_TYPE_REMOTE_GROUP) {
224
-			$result['share_with'] = $share->getSharedWith();
225
-			$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
226
-			$result['token'] = $share->getToken();
227
-		} else if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
228
-			$result['share_with'] = $share->getSharedWith();
229
-			$result['password'] = $share->getPassword();
230
-			$result['send_password_by_talk'] = $share->getSendPasswordByTalk();
231
-			$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
232
-			$result['token'] = $share->getToken();
233
-		} else if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
234
-			// getSharedWith() returns either "name (type, owner)" or
235
-			// "name (type, owner) [id]", depending on the Circles app version.
236
-			$hasCircleId = (substr($share->getSharedWith(), -1) === ']');
237
-
238
-			$result['share_with_displayname'] = $share->getSharedWithDisplayName();
239
-			if (empty($result['share_with_displayname'])) {
240
-				$displayNameLength = ($hasCircleId? strrpos($share->getSharedWith(), ' '): strlen($share->getSharedWith()));
241
-				$result['share_with_displayname'] = substr($share->getSharedWith(), 0, $displayNameLength);
242
-			}
243
-
244
-			$result['share_with_avatar'] = $share->getSharedWithAvatar();
245
-
246
-			$shareWithStart = ($hasCircleId? strrpos($share->getSharedWith(), '[') + 1: 0);
247
-			$shareWithLength = ($hasCircleId? -1: strpos($share->getSharedWith(), ' '));
248
-			if (is_bool($shareWithLength)) {
249
-				$shareWithLength = -1;
250
-			}
251
-			$result['share_with'] = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
252
-		} else if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
253
-			$result['share_with'] = $share->getSharedWith();
254
-			$result['share_with_displayname'] = '';
255
-
256
-			try {
257
-				$result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
258
-			} catch (QueryException $e) {
259
-			}
260
-		}
261
-
262
-
263
-		$result['mail_send'] = $share->getMailSend() ? 1 : 0;
264
-		$result['hide_download'] = $share->getHideDownload() ? 1 : 0;
265
-
266
-		return $result;
267
-	}
268
-
269
-	/**
270
-	 * Check if one of the users address books knows the exact property, if
271
-	 * yes we return the full name.
272
-	 *
273
-	 * @param string $query
274
-	 * @param string $property
275
-	 * @return string
276
-	 */
277
-	private function getDisplayNameFromAddressBook(string $query, string $property): string {
278
-		// FIXME: If we inject the contacts manager it gets initialized bofore any address books are registered
279
-		$result = \OC::$server->getContactsManager()->search($query, [$property]);
280
-		foreach ($result as $r) {
281
-			foreach($r[$property] as $value) {
282
-				if ($value === $query) {
283
-					return $r['FN'];
284
-				}
285
-			}
286
-		}
287
-
288
-		return $query;
289
-	}
290
-
291
-	/**
292
-	 * Get a specific share by id
293
-	 *
294
-	 * @NoAdminRequired
295
-	 *
296
-	 * @param string $id
297
-	 * @return DataResponse
298
-	 * @throws OCSNotFoundException
299
-	 */
300
-	public function getShare(string $id): DataResponse {
301
-		try {
302
-			$share = $this->getShareById($id);
303
-		} catch (ShareNotFound $e) {
304
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
305
-		}
306
-
307
-		if ($this->canAccessShare($share)) {
308
-			try {
309
-				$share = $this->formatShare($share);
310
-				return new DataResponse([$share]);
311
-			} catch (NotFoundException $e) {
312
-				//Fall trough
313
-			}
314
-		}
315
-
316
-		throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
317
-	}
318
-
319
-	/**
320
-	 * Delete a share
321
-	 *
322
-	 * @NoAdminRequired
323
-	 *
324
-	 * @param string $id
325
-	 * @return DataResponse
326
-	 * @throws OCSNotFoundException
327
-	 */
328
-	public function deleteShare(string $id): DataResponse {
329
-		try {
330
-			$share = $this->getShareById($id);
331
-		} catch (ShareNotFound $e) {
332
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
333
-		}
334
-
335
-		try {
336
-			$this->lock($share->getNode());
337
-		} catch (LockedException $e) {
338
-			throw new OCSNotFoundException($this->l->t('could not delete share'));
339
-		}
340
-
341
-		if (!$this->canAccessShare($share)) {
342
-			throw new OCSNotFoundException($this->l->t('Could not delete share'));
343
-		}
344
-
345
-		if (($share->getShareType() === Share::SHARE_TYPE_GROUP ||
346
-				$share->getShareType() === Share::SHARE_TYPE_ROOM) &&
347
-			$share->getShareOwner() !== $this->currentUser &&
348
-			$share->getSharedBy() !== $this->currentUser) {
349
-			$this->shareManager->deleteFromSelf($share, $this->currentUser);
350
-		} else {
351
-			$this->shareManager->deleteShare($share);
352
-		}
353
-
354
-		return new DataResponse();
355
-	}
356
-
357
-	/**
358
-	 * @NoAdminRequired
359
-	 *
360
-	 * @param string $path
361
-	 * @param int $permissions
362
-	 * @param int $shareType
363
-	 * @param string $shareWith
364
-	 * @param string $publicUpload
365
-	 * @param string $password
366
-	 * @param string $sendPasswordByTalk
367
-	 * @param string $expireDate
368
-	 * @param string $label
369
-	 *
370
-	 * @return DataResponse
371
-	 * @throws NotFoundException
372
-	 * @throws OCSBadRequestException
373
-	 * @throws OCSException
374
-	 * @throws OCSForbiddenException
375
-	 * @throws OCSNotFoundException
376
-	 * @throws \OCP\Files\InvalidPathException
377
-	 * @suppress PhanUndeclaredClassMethod
378
-	 */
379
-	public function createShare(
380
-		string $path = null,
381
-		int $permissions = null,
382
-		int $shareType = -1,
383
-		string $shareWith = null,
384
-		string $publicUpload = 'false',
385
-		string $password = '',
386
-		string $sendPasswordByTalk = null,
387
-		string $expireDate = '',
388
-		string $label = ''
389
-	): DataResponse {
390
-		$share = $this->shareManager->newShare();
391
-
392
-		if ($permissions === null) {
393
-			$permissions = $this->config->getAppValue('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL);
394
-		}
395
-
396
-		// Verify path
397
-		if ($path === null) {
398
-			throw new OCSNotFoundException($this->l->t('Please specify a file or folder path'));
399
-		}
400
-
401
-		$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
402
-		try {
403
-			$path = $userFolder->get($path);
404
-		} catch (NotFoundException $e) {
405
-			throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
406
-		}
407
-
408
-		$share->setNode($path);
409
-
410
-		try {
411
-			$this->lock($share->getNode());
412
-		} catch (LockedException $e) {
413
-			throw new OCSNotFoundException($this->l->t('Could not create share'));
414
-		}
415
-
416
-		if ($permissions < 0 || $permissions > Constants::PERMISSION_ALL) {
417
-			throw new OCSNotFoundException($this->l->t('invalid permissions'));
418
-		}
419
-
420
-		// Shares always require read permissions
421
-		$permissions |= Constants::PERMISSION_READ;
422
-
423
-		if ($path instanceof \OCP\Files\File) {
424
-			// Single file shares should never have delete or create permissions
425
-			$permissions &= ~Constants::PERMISSION_DELETE;
426
-			$permissions &= ~Constants::PERMISSION_CREATE;
427
-		}
428
-
429
-		/*
68
+    /** @var IManager */
69
+    private $shareManager;
70
+    /** @var IGroupManager */
71
+    private $groupManager;
72
+    /** @var IUserManager */
73
+    private $userManager;
74
+    /** @var IRootFolder */
75
+    private $rootFolder;
76
+    /** @var IURLGenerator */
77
+    private $urlGenerator;
78
+    /** @var string */
79
+    private $currentUser;
80
+    /** @var IL10N */
81
+    private $l;
82
+    /** @var \OCP\Files\Node */
83
+    private $lockedNode;
84
+    /** @var IConfig */
85
+    private $config;
86
+    /** @var IAppManager */
87
+    private $appManager;
88
+    /** @var IServerContainer */
89
+    private $serverContainer;
90
+
91
+    /**
92
+     * Share20OCS constructor.
93
+     *
94
+     * @param string $appName
95
+     * @param IRequest $request
96
+     * @param IManager $shareManager
97
+     * @param IGroupManager $groupManager
98
+     * @param IUserManager $userManager
99
+     * @param IRootFolder $rootFolder
100
+     * @param IURLGenerator $urlGenerator
101
+     * @param string $userId
102
+     * @param IL10N $l10n
103
+     * @param IConfig $config
104
+     * @param IAppManager $appManager
105
+     * @param IServerContainer $serverContainer
106
+     */
107
+    public function __construct(
108
+        string $appName,
109
+        IRequest $request,
110
+        IManager $shareManager,
111
+        IGroupManager $groupManager,
112
+        IUserManager $userManager,
113
+        IRootFolder $rootFolder,
114
+        IURLGenerator $urlGenerator,
115
+        string $userId = null,
116
+        IL10N $l10n,
117
+        IConfig $config,
118
+        IAppManager $appManager,
119
+        IServerContainer $serverContainer
120
+    ) {
121
+        parent::__construct($appName, $request);
122
+
123
+        $this->shareManager = $shareManager;
124
+        $this->userManager = $userManager;
125
+        $this->groupManager = $groupManager;
126
+        $this->request = $request;
127
+        $this->rootFolder = $rootFolder;
128
+        $this->urlGenerator = $urlGenerator;
129
+        $this->currentUser = $userId;
130
+        $this->l = $l10n;
131
+        $this->config = $config;
132
+        $this->appManager = $appManager;
133
+        $this->serverContainer = $serverContainer;
134
+    }
135
+
136
+    /**
137
+     * Convert an IShare to an array for OCS output
138
+     *
139
+     * @param \OCP\Share\IShare $share
140
+     * @param Node|null $recipientNode
141
+     * @return array
142
+     * @throws NotFoundException In case the node can't be resolved.
143
+     *
144
+     * @suppress PhanUndeclaredClassMethod
145
+     */
146
+    protected function formatShare(\OCP\Share\IShare $share, Node $recipientNode = null): array {
147
+        $sharedBy = $this->userManager->get($share->getSharedBy());
148
+        $shareOwner = $this->userManager->get($share->getShareOwner());
149
+
150
+        $result = [
151
+            'id' => $share->getId(),
152
+            'share_type' => $share->getShareType(),
153
+            'uid_owner' => $share->getSharedBy(),
154
+            'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(),
155
+            'permissions' => $share->getPermissions(),
156
+            'stime' => $share->getShareTime()->getTimestamp(),
157
+            'parent' => null,
158
+            'expiration' => null,
159
+            'token' => null,
160
+            'uid_file_owner' => $share->getShareOwner(),
161
+            'note' => $share->getNote(),
162
+            'label' => $share->getLabel(),
163
+            'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(),
164
+        ];
165
+
166
+        $userFolder = $this->rootFolder->getUserFolder($this->currentUser);
167
+        if ($recipientNode) {
168
+            $node = $recipientNode;
169
+        } else {
170
+            $nodes = $userFolder->getById($share->getNodeId());
171
+            if (empty($nodes)) {
172
+                // fallback to guessing the path
173
+                $node = $userFolder->get($share->getTarget());
174
+                if ($node === null || $share->getTarget() === '') {
175
+                    throw new NotFoundException();
176
+                }
177
+            } else {
178
+                $node = $nodes[0];
179
+            }
180
+        }
181
+
182
+        $result['path'] = $userFolder->getRelativePath($node->getPath());
183
+        if ($node instanceOf \OCP\Files\Folder) {
184
+            $result['item_type'] = 'folder';
185
+        } else {
186
+            $result['item_type'] = 'file';
187
+        }
188
+        $result['mimetype'] = $node->getMimetype();
189
+        $result['storage_id'] = $node->getStorage()->getId();
190
+        $result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
191
+        $result['item_source'] = $node->getId();
192
+        $result['file_source'] = $node->getId();
193
+        $result['file_parent'] = $node->getParent()->getId();
194
+        $result['file_target'] = $share->getTarget();
195
+
196
+        $expiration = $share->getExpirationDate();
197
+        if ($expiration !== null) {
198
+            $result['expiration'] = $expiration->format('Y-m-d 00:00:00');
199
+        }
200
+
201
+        if ($share->getShareType() === Share::SHARE_TYPE_USER) {
202
+            $sharedWith = $this->userManager->get($share->getSharedWith());
203
+            $result['share_with'] = $share->getSharedWith();
204
+            $result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith();
205
+        } else if ($share->getShareType() === Share::SHARE_TYPE_GROUP) {
206
+            $group = $this->groupManager->get($share->getSharedWith());
207
+            $result['share_with'] = $share->getSharedWith();
208
+            $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
209
+        } else if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
210
+
211
+            // "share_with" and "share_with_displayname" for passwords of link
212
+            // shares was deprecated in Nextcloud 15, use "password" instead.
213
+            $result['share_with'] = $share->getPassword();
214
+            $result['share_with_displayname'] = $share->getPassword();
215
+
216
+            $result['password'] = $share->getPassword();
217
+
218
+            $result['send_password_by_talk'] = $share->getSendPasswordByTalk();
219
+
220
+            $result['token'] = $share->getToken();
221
+            $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
222
+
223
+        } else if ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() === Share::SHARE_TYPE_REMOTE_GROUP) {
224
+            $result['share_with'] = $share->getSharedWith();
225
+            $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
226
+            $result['token'] = $share->getToken();
227
+        } else if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
228
+            $result['share_with'] = $share->getSharedWith();
229
+            $result['password'] = $share->getPassword();
230
+            $result['send_password_by_talk'] = $share->getSendPasswordByTalk();
231
+            $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
232
+            $result['token'] = $share->getToken();
233
+        } else if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
234
+            // getSharedWith() returns either "name (type, owner)" or
235
+            // "name (type, owner) [id]", depending on the Circles app version.
236
+            $hasCircleId = (substr($share->getSharedWith(), -1) === ']');
237
+
238
+            $result['share_with_displayname'] = $share->getSharedWithDisplayName();
239
+            if (empty($result['share_with_displayname'])) {
240
+                $displayNameLength = ($hasCircleId? strrpos($share->getSharedWith(), ' '): strlen($share->getSharedWith()));
241
+                $result['share_with_displayname'] = substr($share->getSharedWith(), 0, $displayNameLength);
242
+            }
243
+
244
+            $result['share_with_avatar'] = $share->getSharedWithAvatar();
245
+
246
+            $shareWithStart = ($hasCircleId? strrpos($share->getSharedWith(), '[') + 1: 0);
247
+            $shareWithLength = ($hasCircleId? -1: strpos($share->getSharedWith(), ' '));
248
+            if (is_bool($shareWithLength)) {
249
+                $shareWithLength = -1;
250
+            }
251
+            $result['share_with'] = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
252
+        } else if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
253
+            $result['share_with'] = $share->getSharedWith();
254
+            $result['share_with_displayname'] = '';
255
+
256
+            try {
257
+                $result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
258
+            } catch (QueryException $e) {
259
+            }
260
+        }
261
+
262
+
263
+        $result['mail_send'] = $share->getMailSend() ? 1 : 0;
264
+        $result['hide_download'] = $share->getHideDownload() ? 1 : 0;
265
+
266
+        return $result;
267
+    }
268
+
269
+    /**
270
+     * Check if one of the users address books knows the exact property, if
271
+     * yes we return the full name.
272
+     *
273
+     * @param string $query
274
+     * @param string $property
275
+     * @return string
276
+     */
277
+    private function getDisplayNameFromAddressBook(string $query, string $property): string {
278
+        // FIXME: If we inject the contacts manager it gets initialized bofore any address books are registered
279
+        $result = \OC::$server->getContactsManager()->search($query, [$property]);
280
+        foreach ($result as $r) {
281
+            foreach($r[$property] as $value) {
282
+                if ($value === $query) {
283
+                    return $r['FN'];
284
+                }
285
+            }
286
+        }
287
+
288
+        return $query;
289
+    }
290
+
291
+    /**
292
+     * Get a specific share by id
293
+     *
294
+     * @NoAdminRequired
295
+     *
296
+     * @param string $id
297
+     * @return DataResponse
298
+     * @throws OCSNotFoundException
299
+     */
300
+    public function getShare(string $id): DataResponse {
301
+        try {
302
+            $share = $this->getShareById($id);
303
+        } catch (ShareNotFound $e) {
304
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
305
+        }
306
+
307
+        if ($this->canAccessShare($share)) {
308
+            try {
309
+                $share = $this->formatShare($share);
310
+                return new DataResponse([$share]);
311
+            } catch (NotFoundException $e) {
312
+                //Fall trough
313
+            }
314
+        }
315
+
316
+        throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
317
+    }
318
+
319
+    /**
320
+     * Delete a share
321
+     *
322
+     * @NoAdminRequired
323
+     *
324
+     * @param string $id
325
+     * @return DataResponse
326
+     * @throws OCSNotFoundException
327
+     */
328
+    public function deleteShare(string $id): DataResponse {
329
+        try {
330
+            $share = $this->getShareById($id);
331
+        } catch (ShareNotFound $e) {
332
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
333
+        }
334
+
335
+        try {
336
+            $this->lock($share->getNode());
337
+        } catch (LockedException $e) {
338
+            throw new OCSNotFoundException($this->l->t('could not delete share'));
339
+        }
340
+
341
+        if (!$this->canAccessShare($share)) {
342
+            throw new OCSNotFoundException($this->l->t('Could not delete share'));
343
+        }
344
+
345
+        if (($share->getShareType() === Share::SHARE_TYPE_GROUP ||
346
+                $share->getShareType() === Share::SHARE_TYPE_ROOM) &&
347
+            $share->getShareOwner() !== $this->currentUser &&
348
+            $share->getSharedBy() !== $this->currentUser) {
349
+            $this->shareManager->deleteFromSelf($share, $this->currentUser);
350
+        } else {
351
+            $this->shareManager->deleteShare($share);
352
+        }
353
+
354
+        return new DataResponse();
355
+    }
356
+
357
+    /**
358
+     * @NoAdminRequired
359
+     *
360
+     * @param string $path
361
+     * @param int $permissions
362
+     * @param int $shareType
363
+     * @param string $shareWith
364
+     * @param string $publicUpload
365
+     * @param string $password
366
+     * @param string $sendPasswordByTalk
367
+     * @param string $expireDate
368
+     * @param string $label
369
+     *
370
+     * @return DataResponse
371
+     * @throws NotFoundException
372
+     * @throws OCSBadRequestException
373
+     * @throws OCSException
374
+     * @throws OCSForbiddenException
375
+     * @throws OCSNotFoundException
376
+     * @throws \OCP\Files\InvalidPathException
377
+     * @suppress PhanUndeclaredClassMethod
378
+     */
379
+    public function createShare(
380
+        string $path = null,
381
+        int $permissions = null,
382
+        int $shareType = -1,
383
+        string $shareWith = null,
384
+        string $publicUpload = 'false',
385
+        string $password = '',
386
+        string $sendPasswordByTalk = null,
387
+        string $expireDate = '',
388
+        string $label = ''
389
+    ): DataResponse {
390
+        $share = $this->shareManager->newShare();
391
+
392
+        if ($permissions === null) {
393
+            $permissions = $this->config->getAppValue('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL);
394
+        }
395
+
396
+        // Verify path
397
+        if ($path === null) {
398
+            throw new OCSNotFoundException($this->l->t('Please specify a file or folder path'));
399
+        }
400
+
401
+        $userFolder = $this->rootFolder->getUserFolder($this->currentUser);
402
+        try {
403
+            $path = $userFolder->get($path);
404
+        } catch (NotFoundException $e) {
405
+            throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
406
+        }
407
+
408
+        $share->setNode($path);
409
+
410
+        try {
411
+            $this->lock($share->getNode());
412
+        } catch (LockedException $e) {
413
+            throw new OCSNotFoundException($this->l->t('Could not create share'));
414
+        }
415
+
416
+        if ($permissions < 0 || $permissions > Constants::PERMISSION_ALL) {
417
+            throw new OCSNotFoundException($this->l->t('invalid permissions'));
418
+        }
419
+
420
+        // Shares always require read permissions
421
+        $permissions |= Constants::PERMISSION_READ;
422
+
423
+        if ($path instanceof \OCP\Files\File) {
424
+            // Single file shares should never have delete or create permissions
425
+            $permissions &= ~Constants::PERMISSION_DELETE;
426
+            $permissions &= ~Constants::PERMISSION_CREATE;
427
+        }
428
+
429
+        /*
430 430
 		 * Hack for https://github.com/owncloud/core/issues/22587
431 431
 		 * We check the permissions via webdav. But the permissions of the mount point
432 432
 		 * do not equal the share permissions. Here we fix that for federated mounts.
433 433
 		 */
434
-		if ($path->getStorage()->instanceOfStorage(Storage::class)) {
435
-			$permissions &= ~($permissions & ~$path->getPermissions());
436
-		}
437
-
438
-		if ($shareType === Share::SHARE_TYPE_USER) {
439
-			// Valid user is required to share
440
-			if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
441
-				throw new OCSNotFoundException($this->l->t('Please specify a valid user'));
442
-			}
443
-			$share->setSharedWith($shareWith);
444
-			$share->setPermissions($permissions);
445
-		} else if ($shareType === Share::SHARE_TYPE_GROUP) {
446
-			if (!$this->shareManager->allowGroupSharing()) {
447
-				throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator'));
448
-			}
449
-
450
-			// Valid group is required to share
451
-			if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
452
-				throw new OCSNotFoundException($this->l->t('Please specify a valid group'));
453
-			}
454
-			$share->setSharedWith($shareWith);
455
-			$share->setPermissions($permissions);
456
-		} else if ($shareType === Share::SHARE_TYPE_LINK) {
457
-			//Can we even share links?
458
-			if (!$this->shareManager->shareApiAllowLinks()) {
459
-				throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator'));
460
-			}
461
-
462
-			if ($publicUpload === 'true') {
463
-				// Check if public upload is allowed
464
-				if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
465
-					throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
466
-				}
467
-
468
-				// Public upload can only be set for folders
469
-				if ($path instanceof \OCP\Files\File) {
470
-					throw new OCSNotFoundException($this->l->t('Public upload is only possible for publicly shared folders'));
471
-				}
472
-
473
-				$share->setPermissions(
474
-					Constants::PERMISSION_READ |
475
-					Constants::PERMISSION_CREATE |
476
-					Constants::PERMISSION_UPDATE |
477
-					Constants::PERMISSION_DELETE
478
-				);
479
-			} else {
480
-				$share->setPermissions(Constants::PERMISSION_READ);
481
-			}
482
-
483
-			// Set password
484
-			if ($password !== '') {
485
-				$share->setPassword($password);
486
-			}
487
-
488
-
489
-			if (!empty($label)) {
490
-				$share->setLabel($label);
491
-			}
492
-
493
-			if ($sendPasswordByTalk === 'true') {
494
-				if (!$this->appManager->isEnabledForUser('spreed')) {
495
-					throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()]));
496
-				}
497
-
498
-				$share->setSendPasswordByTalk(true);
499
-			}
500
-
501
-			//Expire date
502
-			if ($expireDate !== '') {
503
-				try {
504
-					$expireDate = $this->parseDate($expireDate);
505
-					$share->setExpirationDate($expireDate);
506
-				} catch (\Exception $e) {
507
-					throw new OCSNotFoundException($this->l->t('Invalid date, date format must be YYYY-MM-DD'));
508
-				}
509
-			}
510
-
511
-		} else if ($shareType === Share::SHARE_TYPE_REMOTE) {
512
-			if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
513
-				throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
514
-			}
515
-
516
-			$share->setSharedWith($shareWith);
517
-			$share->setPermissions($permissions);
518
-		}  else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) {
519
-			if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
520
-				throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
521
-			}
522
-
523
-			$share->setSharedWith($shareWith);
524
-			$share->setPermissions($permissions);
525
-		} else if ($shareType === Share::SHARE_TYPE_EMAIL) {
526
-			if ($share->getNodeType() === 'file') {
527
-				$share->setPermissions(Constants::PERMISSION_READ);
528
-			} else {
529
-				$share->setPermissions($permissions);
530
-			}
531
-			$share->setSharedWith($shareWith);
532
-
533
-			if ($sendPasswordByTalk === 'true') {
534
-				if (!$this->appManager->isEnabledForUser('spreed')) {
535
-					throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()]));
536
-				}
537
-
538
-				$share->setSendPasswordByTalk(true);
539
-			}
540
-		} else if ($shareType === Share::SHARE_TYPE_CIRCLE) {
541
-			if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) {
542
-				throw new OCSNotFoundException($this->l->t('You cannot share to a Circle if the app is not enabled'));
543
-			}
544
-
545
-			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($shareWith);
546
-
547
-			// Valid circle is required to share
548
-			if ($circle === null) {
549
-				throw new OCSNotFoundException($this->l->t('Please specify a valid circle'));
550
-			}
551
-			$share->setSharedWith($shareWith);
552
-			$share->setPermissions($permissions);
553
-		} else if ($shareType === Share::SHARE_TYPE_ROOM) {
554
-			try {
555
-				$this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate);
556
-			} catch (QueryException $e) {
557
-				throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()]));
558
-			}
559
-		} else {
560
-			throw new OCSBadRequestException($this->l->t('Unknown share type'));
561
-		}
562
-
563
-		$share->setShareType($shareType);
564
-		$share->setSharedBy($this->currentUser);
565
-
566
-		try {
567
-			$share = $this->shareManager->createShare($share);
568
-		} catch (GenericShareException $e) {
569
-			$code = $e->getCode() === 0 ? 403 : $e->getCode();
570
-			throw new OCSException($e->getHint(), $code);
571
-		} catch (\Exception $e) {
572
-			throw new OCSForbiddenException($e->getMessage(), $e);
573
-		}
574
-
575
-		$output = $this->formatShare($share);
576
-
577
-		return new DataResponse($output);
578
-	}
579
-
580
-	/**
581
-	 * @param \OCP\Files\File|\OCP\Files\Folder $node
582
-	 * @param boolean $includeTags
583
-	 * @return DataResponse
584
-	 */
585
-	private function getSharedWithMe($node = null, bool $includeTags): DataResponse {
586
-
587
-		$userShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $node, -1, 0);
588
-		$groupShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $node, -1, 0);
589
-		$circleShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_CIRCLE, $node, -1, 0);
590
-		$roomShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $node, -1, 0);
591
-
592
-		$shares = array_merge($userShares, $groupShares, $circleShares, $roomShares);
593
-
594
-		$shares = array_filter($shares, function (IShare $share) {
595
-			return $share->getShareOwner() !== $this->currentUser;
596
-		});
597
-
598
-		$formatted = [];
599
-		foreach ($shares as $share) {
600
-			if ($this->canAccessShare($share)) {
601
-				try {
602
-					$formatted[] = $this->formatShare($share);
603
-				} catch (NotFoundException $e) {
604
-					// Ignore this share
605
-				}
606
-			}
607
-		}
608
-
609
-		if ($includeTags) {
610
-			$formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
611
-		}
612
-
613
-		return new DataResponse($formatted);
614
-	}
615
-
616
-	/**
617
-	 * @param \OCP\Files\Folder $folder
618
-	 * @return DataResponse
619
-	 * @throws OCSBadRequestException
620
-	 */
621
-	private function getSharesInDir(Node $folder): DataResponse {
622
-		if (!($folder instanceof \OCP\Files\Folder)) {
623
-			throw new OCSBadRequestException($this->l->t('Not a directory'));
624
-		}
625
-
626
-		$nodes = $folder->getDirectoryListing();
627
-		/** @var \OCP\Share\IShare[] $shares */
628
-		$shares = [];
629
-		foreach ($nodes as $node) {
630
-
631
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $node, true, -1, 0));
632
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $node, true, -1, 0));
633
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $node, true, -1, 0));
634
-			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
635
-				$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $node, true, -1, 0));
636
-			}
637
-			if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
638
-				$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, true, -1, 0));
639
-			}
640
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $node, true, -1, 0));
641
-		}
642
-
643
-		$formatted = $miniFormatted = [];
644
-		$resharingRight = false;
645
-		$known = [];
646
-		foreach ($shares as $share) {
647
-			if (in_array($share->getId(), $known) || $share->getSharedWith() === $this->currentUser) {
648
-				continue;
649
-			}
650
-
651
-			try {
652
-				$format = $this->formatShare($share);
653
-
654
-				$known[] = $share->getId();
655
-				$formatted[] = $format;
656
-				if ($share->getSharedBy() === $this->currentUser) {
657
-					$miniFormatted[] = $format;
658
-				}
659
-				if (!$resharingRight && $this->shareProviderResharingRights($this->currentUser, $share, $folder)) {
660
-					$resharingRight = true;
661
-				}
662
-			} catch (\Exception $e) {
663
-				//Ignore this share
664
-			}
665
-		}
666
-
667
-		if (!$resharingRight) {
668
-			$formatted = $miniFormatted;
669
-		}
670
-
671
-		return new DataResponse($formatted);
672
-	}
673
-
674
-	/**
675
-	 * The getShares function.
676
-	 *
677
-	 * @NoAdminRequired
678
-	 *
679
-	 * @param string $shared_with_me
680
-	 * @param string $reshares
681
-	 * @param string $subfiles
682
-	 * @param string $path
683
-	 *
684
-	 * - Get shares by the current user
685
-	 * - Get shares by the current user and reshares (?reshares=true)
686
-	 * - Get shares with the current user (?shared_with_me=true)
687
-	 * - Get shares for a specific path (?path=...)
688
-	 * - Get all shares in a folder (?subfiles=true&path=..)
689
-	 *
690
-	 * @return DataResponse
691
-	 * @throws OCSNotFoundException
692
-	 */
693
-	public function getShares(
694
-		string $shared_with_me = 'false',
695
-		string $reshares = 'false',
696
-		string $subfiles = 'false',
697
-		string $path = null,
698
-		string $include_tags = 'false'
699
-	): DataResponse {
700
-
701
-		if ($path !== null) {
702
-			$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
703
-			try {
704
-				$path = $userFolder->get($path);
705
-				$this->lock($path);
706
-			} catch (\OCP\Files\NotFoundException $e) {
707
-				throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
708
-			} catch (LockedException $e) {
709
-				throw new OCSNotFoundException($this->l->t('Could not lock path'));
710
-			}
711
-		}
712
-
713
-		$include_tags = $include_tags === 'true';
714
-
715
-		if ($shared_with_me === 'true') {
716
-			$result = $this->getSharedWithMe($path, $include_tags);
717
-			return $result;
718
-		}
719
-
720
-		if ($subfiles === 'true') {
721
-			$result = $this->getSharesInDir($path);
722
-			return $result;
723
-		}
724
-
725
-		if ($reshares === 'true') {
726
-			$reshares = true;
727
-		} else {
728
-			$reshares = false;
729
-		}
730
-
731
-		// Get all shares
732
-		$userShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
733
-		$groupShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
734
-		$linkShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
735
-		if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
736
-			$mailShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0);
737
-		} else {
738
-			$mailShares = [];
739
-		}
740
-		if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
741
-			$circleShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0);
742
-		} else {
743
-			$circleShares = [];
744
-		}
745
-		$roomShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $path, $reshares, -1, 0);
746
-
747
-		$shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares);
748
-
749
-		if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
750
-			$federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
751
-			$shares = array_merge($shares, $federatedShares);
752
-		}
753
-
754
-		if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
755
-			$federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE_GROUP, $path, $reshares, -1, 0);
756
-			$shares = array_merge($shares, $federatedShares);
757
-		}
758
-
759
-		$formatted = $miniFormatted = [];
760
-		$resharingRight = false;
761
-		foreach ($shares as $share) {
762
-			/** @var IShare $share */
763
-			try {
764
-				$format = $this->formatShare($share, $path);
765
-				$formatted[] = $format;
766
-				if ($share->getSharedBy() === $this->currentUser) {
767
-					$miniFormatted[] = $format;
768
-				}
769
-
770
-				if (!$resharingRight && $this->shareProviderResharingRights($this->currentUser, $share, $path)) {
771
-					$resharingRight = true;
772
-				}
773
-			} catch (\Exception $e) {
774
-				//Ignore share
775
-			}
776
-		}
777
-
778
-		if (!$resharingRight) {
779
-			$formatted = $miniFormatted;
780
-		}
781
-
782
-		if ($include_tags) {
783
-			$formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
784
-		}
785
-
786
-		return new DataResponse($formatted);
787
-	}
788
-
789
-	/**
790
-	 * @NoAdminRequired
791
-	 *
792
-	 * @param string $id
793
-	 * @param int $permissions
794
-	 * @param string $password
795
-	 * @param string $sendPasswordByTalk
796
-	 * @param string $publicUpload
797
-	 * @param string $expireDate
798
-	 * @param string $note
799
-	 * @param string $label
800
-	 * @param string $hideDownload
801
-	 * @return DataResponse
802
-	 * @throws LockedException
803
-	 * @throws NotFoundException
804
-	 * @throws OCSBadRequestException
805
-	 * @throws OCSForbiddenException
806
-	 * @throws OCSNotFoundException
807
-	 */
808
-	public function updateShare(
809
-		string $id,
810
-		int $permissions = null,
811
-		string $password = null,
812
-		string $sendPasswordByTalk = null,
813
-		string $publicUpload = null,
814
-		string $expireDate = null,
815
-		string $note = null,
816
-		string $label = null,
817
-		string $hideDownload = null
818
-	): DataResponse {
819
-		try {
820
-			$share = $this->getShareById($id);
821
-		} catch (ShareNotFound $e) {
822
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
823
-		}
824
-
825
-		$this->lock($share->getNode());
826
-
827
-		if (!$this->canAccessShare($share, false)) {
828
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
829
-		}
830
-
831
-		if ($share->getShareOwner() !== $this->currentUser && $share->getSharedBy() !== $this->currentUser) {
832
-			throw new OCSForbiddenException('You are not allowed to edit incoming shares');
833
-		}
834
-
835
-		if ($permissions === null &&
836
-			$password === null &&
837
-			$sendPasswordByTalk === null &&
838
-			$publicUpload === null &&
839
-			$expireDate === null &&
840
-			$note === null &&
841
-			$label === null &&
842
-			$hideDownload === null
843
-		) {
844
-			throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
845
-		}
846
-
847
-		if($note !== null) {
848
-			$share->setNote($note);
849
-		}
850
-
851
-		/*
434
+        if ($path->getStorage()->instanceOfStorage(Storage::class)) {
435
+            $permissions &= ~($permissions & ~$path->getPermissions());
436
+        }
437
+
438
+        if ($shareType === Share::SHARE_TYPE_USER) {
439
+            // Valid user is required to share
440
+            if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
441
+                throw new OCSNotFoundException($this->l->t('Please specify a valid user'));
442
+            }
443
+            $share->setSharedWith($shareWith);
444
+            $share->setPermissions($permissions);
445
+        } else if ($shareType === Share::SHARE_TYPE_GROUP) {
446
+            if (!$this->shareManager->allowGroupSharing()) {
447
+                throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator'));
448
+            }
449
+
450
+            // Valid group is required to share
451
+            if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
452
+                throw new OCSNotFoundException($this->l->t('Please specify a valid group'));
453
+            }
454
+            $share->setSharedWith($shareWith);
455
+            $share->setPermissions($permissions);
456
+        } else if ($shareType === Share::SHARE_TYPE_LINK) {
457
+            //Can we even share links?
458
+            if (!$this->shareManager->shareApiAllowLinks()) {
459
+                throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator'));
460
+            }
461
+
462
+            if ($publicUpload === 'true') {
463
+                // Check if public upload is allowed
464
+                if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
465
+                    throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
466
+                }
467
+
468
+                // Public upload can only be set for folders
469
+                if ($path instanceof \OCP\Files\File) {
470
+                    throw new OCSNotFoundException($this->l->t('Public upload is only possible for publicly shared folders'));
471
+                }
472
+
473
+                $share->setPermissions(
474
+                    Constants::PERMISSION_READ |
475
+                    Constants::PERMISSION_CREATE |
476
+                    Constants::PERMISSION_UPDATE |
477
+                    Constants::PERMISSION_DELETE
478
+                );
479
+            } else {
480
+                $share->setPermissions(Constants::PERMISSION_READ);
481
+            }
482
+
483
+            // Set password
484
+            if ($password !== '') {
485
+                $share->setPassword($password);
486
+            }
487
+
488
+
489
+            if (!empty($label)) {
490
+                $share->setLabel($label);
491
+            }
492
+
493
+            if ($sendPasswordByTalk === 'true') {
494
+                if (!$this->appManager->isEnabledForUser('spreed')) {
495
+                    throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()]));
496
+                }
497
+
498
+                $share->setSendPasswordByTalk(true);
499
+            }
500
+
501
+            //Expire date
502
+            if ($expireDate !== '') {
503
+                try {
504
+                    $expireDate = $this->parseDate($expireDate);
505
+                    $share->setExpirationDate($expireDate);
506
+                } catch (\Exception $e) {
507
+                    throw new OCSNotFoundException($this->l->t('Invalid date, date format must be YYYY-MM-DD'));
508
+                }
509
+            }
510
+
511
+        } else if ($shareType === Share::SHARE_TYPE_REMOTE) {
512
+            if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
513
+                throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
514
+            }
515
+
516
+            $share->setSharedWith($shareWith);
517
+            $share->setPermissions($permissions);
518
+        }  else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) {
519
+            if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
520
+                throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
521
+            }
522
+
523
+            $share->setSharedWith($shareWith);
524
+            $share->setPermissions($permissions);
525
+        } else if ($shareType === Share::SHARE_TYPE_EMAIL) {
526
+            if ($share->getNodeType() === 'file') {
527
+                $share->setPermissions(Constants::PERMISSION_READ);
528
+            } else {
529
+                $share->setPermissions($permissions);
530
+            }
531
+            $share->setSharedWith($shareWith);
532
+
533
+            if ($sendPasswordByTalk === 'true') {
534
+                if (!$this->appManager->isEnabledForUser('spreed')) {
535
+                    throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()]));
536
+                }
537
+
538
+                $share->setSendPasswordByTalk(true);
539
+            }
540
+        } else if ($shareType === Share::SHARE_TYPE_CIRCLE) {
541
+            if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) {
542
+                throw new OCSNotFoundException($this->l->t('You cannot share to a Circle if the app is not enabled'));
543
+            }
544
+
545
+            $circle = \OCA\Circles\Api\v1\Circles::detailsCircle($shareWith);
546
+
547
+            // Valid circle is required to share
548
+            if ($circle === null) {
549
+                throw new OCSNotFoundException($this->l->t('Please specify a valid circle'));
550
+            }
551
+            $share->setSharedWith($shareWith);
552
+            $share->setPermissions($permissions);
553
+        } else if ($shareType === Share::SHARE_TYPE_ROOM) {
554
+            try {
555
+                $this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate);
556
+            } catch (QueryException $e) {
557
+                throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()]));
558
+            }
559
+        } else {
560
+            throw new OCSBadRequestException($this->l->t('Unknown share type'));
561
+        }
562
+
563
+        $share->setShareType($shareType);
564
+        $share->setSharedBy($this->currentUser);
565
+
566
+        try {
567
+            $share = $this->shareManager->createShare($share);
568
+        } catch (GenericShareException $e) {
569
+            $code = $e->getCode() === 0 ? 403 : $e->getCode();
570
+            throw new OCSException($e->getHint(), $code);
571
+        } catch (\Exception $e) {
572
+            throw new OCSForbiddenException($e->getMessage(), $e);
573
+        }
574
+
575
+        $output = $this->formatShare($share);
576
+
577
+        return new DataResponse($output);
578
+    }
579
+
580
+    /**
581
+     * @param \OCP\Files\File|\OCP\Files\Folder $node
582
+     * @param boolean $includeTags
583
+     * @return DataResponse
584
+     */
585
+    private function getSharedWithMe($node = null, bool $includeTags): DataResponse {
586
+
587
+        $userShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $node, -1, 0);
588
+        $groupShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $node, -1, 0);
589
+        $circleShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_CIRCLE, $node, -1, 0);
590
+        $roomShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $node, -1, 0);
591
+
592
+        $shares = array_merge($userShares, $groupShares, $circleShares, $roomShares);
593
+
594
+        $shares = array_filter($shares, function (IShare $share) {
595
+            return $share->getShareOwner() !== $this->currentUser;
596
+        });
597
+
598
+        $formatted = [];
599
+        foreach ($shares as $share) {
600
+            if ($this->canAccessShare($share)) {
601
+                try {
602
+                    $formatted[] = $this->formatShare($share);
603
+                } catch (NotFoundException $e) {
604
+                    // Ignore this share
605
+                }
606
+            }
607
+        }
608
+
609
+        if ($includeTags) {
610
+            $formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
611
+        }
612
+
613
+        return new DataResponse($formatted);
614
+    }
615
+
616
+    /**
617
+     * @param \OCP\Files\Folder $folder
618
+     * @return DataResponse
619
+     * @throws OCSBadRequestException
620
+     */
621
+    private function getSharesInDir(Node $folder): DataResponse {
622
+        if (!($folder instanceof \OCP\Files\Folder)) {
623
+            throw new OCSBadRequestException($this->l->t('Not a directory'));
624
+        }
625
+
626
+        $nodes = $folder->getDirectoryListing();
627
+        /** @var \OCP\Share\IShare[] $shares */
628
+        $shares = [];
629
+        foreach ($nodes as $node) {
630
+
631
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $node, true, -1, 0));
632
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $node, true, -1, 0));
633
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $node, true, -1, 0));
634
+            if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
635
+                $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $node, true, -1, 0));
636
+            }
637
+            if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
638
+                $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, true, -1, 0));
639
+            }
640
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $node, true, -1, 0));
641
+        }
642
+
643
+        $formatted = $miniFormatted = [];
644
+        $resharingRight = false;
645
+        $known = [];
646
+        foreach ($shares as $share) {
647
+            if (in_array($share->getId(), $known) || $share->getSharedWith() === $this->currentUser) {
648
+                continue;
649
+            }
650
+
651
+            try {
652
+                $format = $this->formatShare($share);
653
+
654
+                $known[] = $share->getId();
655
+                $formatted[] = $format;
656
+                if ($share->getSharedBy() === $this->currentUser) {
657
+                    $miniFormatted[] = $format;
658
+                }
659
+                if (!$resharingRight && $this->shareProviderResharingRights($this->currentUser, $share, $folder)) {
660
+                    $resharingRight = true;
661
+                }
662
+            } catch (\Exception $e) {
663
+                //Ignore this share
664
+            }
665
+        }
666
+
667
+        if (!$resharingRight) {
668
+            $formatted = $miniFormatted;
669
+        }
670
+
671
+        return new DataResponse($formatted);
672
+    }
673
+
674
+    /**
675
+     * The getShares function.
676
+     *
677
+     * @NoAdminRequired
678
+     *
679
+     * @param string $shared_with_me
680
+     * @param string $reshares
681
+     * @param string $subfiles
682
+     * @param string $path
683
+     *
684
+     * - Get shares by the current user
685
+     * - Get shares by the current user and reshares (?reshares=true)
686
+     * - Get shares with the current user (?shared_with_me=true)
687
+     * - Get shares for a specific path (?path=...)
688
+     * - Get all shares in a folder (?subfiles=true&path=..)
689
+     *
690
+     * @return DataResponse
691
+     * @throws OCSNotFoundException
692
+     */
693
+    public function getShares(
694
+        string $shared_with_me = 'false',
695
+        string $reshares = 'false',
696
+        string $subfiles = 'false',
697
+        string $path = null,
698
+        string $include_tags = 'false'
699
+    ): DataResponse {
700
+
701
+        if ($path !== null) {
702
+            $userFolder = $this->rootFolder->getUserFolder($this->currentUser);
703
+            try {
704
+                $path = $userFolder->get($path);
705
+                $this->lock($path);
706
+            } catch (\OCP\Files\NotFoundException $e) {
707
+                throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
708
+            } catch (LockedException $e) {
709
+                throw new OCSNotFoundException($this->l->t('Could not lock path'));
710
+            }
711
+        }
712
+
713
+        $include_tags = $include_tags === 'true';
714
+
715
+        if ($shared_with_me === 'true') {
716
+            $result = $this->getSharedWithMe($path, $include_tags);
717
+            return $result;
718
+        }
719
+
720
+        if ($subfiles === 'true') {
721
+            $result = $this->getSharesInDir($path);
722
+            return $result;
723
+        }
724
+
725
+        if ($reshares === 'true') {
726
+            $reshares = true;
727
+        } else {
728
+            $reshares = false;
729
+        }
730
+
731
+        // Get all shares
732
+        $userShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
733
+        $groupShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
734
+        $linkShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
735
+        if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
736
+            $mailShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0);
737
+        } else {
738
+            $mailShares = [];
739
+        }
740
+        if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
741
+            $circleShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0);
742
+        } else {
743
+            $circleShares = [];
744
+        }
745
+        $roomShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $path, $reshares, -1, 0);
746
+
747
+        $shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares);
748
+
749
+        if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
750
+            $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
751
+            $shares = array_merge($shares, $federatedShares);
752
+        }
753
+
754
+        if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
755
+            $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE_GROUP, $path, $reshares, -1, 0);
756
+            $shares = array_merge($shares, $federatedShares);
757
+        }
758
+
759
+        $formatted = $miniFormatted = [];
760
+        $resharingRight = false;
761
+        foreach ($shares as $share) {
762
+            /** @var IShare $share */
763
+            try {
764
+                $format = $this->formatShare($share, $path);
765
+                $formatted[] = $format;
766
+                if ($share->getSharedBy() === $this->currentUser) {
767
+                    $miniFormatted[] = $format;
768
+                }
769
+
770
+                if (!$resharingRight && $this->shareProviderResharingRights($this->currentUser, $share, $path)) {
771
+                    $resharingRight = true;
772
+                }
773
+            } catch (\Exception $e) {
774
+                //Ignore share
775
+            }
776
+        }
777
+
778
+        if (!$resharingRight) {
779
+            $formatted = $miniFormatted;
780
+        }
781
+
782
+        if ($include_tags) {
783
+            $formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
784
+        }
785
+
786
+        return new DataResponse($formatted);
787
+    }
788
+
789
+    /**
790
+     * @NoAdminRequired
791
+     *
792
+     * @param string $id
793
+     * @param int $permissions
794
+     * @param string $password
795
+     * @param string $sendPasswordByTalk
796
+     * @param string $publicUpload
797
+     * @param string $expireDate
798
+     * @param string $note
799
+     * @param string $label
800
+     * @param string $hideDownload
801
+     * @return DataResponse
802
+     * @throws LockedException
803
+     * @throws NotFoundException
804
+     * @throws OCSBadRequestException
805
+     * @throws OCSForbiddenException
806
+     * @throws OCSNotFoundException
807
+     */
808
+    public function updateShare(
809
+        string $id,
810
+        int $permissions = null,
811
+        string $password = null,
812
+        string $sendPasswordByTalk = null,
813
+        string $publicUpload = null,
814
+        string $expireDate = null,
815
+        string $note = null,
816
+        string $label = null,
817
+        string $hideDownload = null
818
+    ): DataResponse {
819
+        try {
820
+            $share = $this->getShareById($id);
821
+        } catch (ShareNotFound $e) {
822
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
823
+        }
824
+
825
+        $this->lock($share->getNode());
826
+
827
+        if (!$this->canAccessShare($share, false)) {
828
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
829
+        }
830
+
831
+        if ($share->getShareOwner() !== $this->currentUser && $share->getSharedBy() !== $this->currentUser) {
832
+            throw new OCSForbiddenException('You are not allowed to edit incoming shares');
833
+        }
834
+
835
+        if ($permissions === null &&
836
+            $password === null &&
837
+            $sendPasswordByTalk === null &&
838
+            $publicUpload === null &&
839
+            $expireDate === null &&
840
+            $note === null &&
841
+            $label === null &&
842
+            $hideDownload === null
843
+        ) {
844
+            throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
845
+        }
846
+
847
+        if($note !== null) {
848
+            $share->setNote($note);
849
+        }
850
+
851
+        /*
852 852
 		 * expirationdate, password and publicUpload only make sense for link shares
853 853
 		 */
854
-		if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
855
-
856
-			// Update hide download state
857
-			if ($hideDownload === 'true') {
858
-				$share->setHideDownload(true);
859
-			} else if ($hideDownload === 'false') {
860
-				$share->setHideDownload(false);
861
-			}
862
-
863
-			$newPermissions = null;
864
-			if ($publicUpload === 'true') {
865
-				$newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
866
-			} else if ($publicUpload === 'false') {
867
-				$newPermissions = Constants::PERMISSION_READ;
868
-			}
869
-
870
-			if ($permissions !== null) {
871
-				$newPermissions = (int)$permissions;
872
-				$newPermissions = $newPermissions & ~Constants::PERMISSION_SHARE;
873
-			}
874
-
875
-			if ($newPermissions !== null &&
876
-				!in_array($newPermissions, [
877
-					Constants::PERMISSION_READ,
878
-					Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE, // legacy
879
-					Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE, // correct
880
-					Constants::PERMISSION_CREATE, // hidden file list
881
-					Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE, // allow to edit single files
882
-				], true)
883
-			) {
884
-				throw new OCSBadRequestException($this->l->t('Can\'t change permissions for public share links'));
885
-			}
886
-
887
-			if (
888
-				// legacy
889
-				$newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE) ||
890
-				// correct
891
-				$newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
892
-			) {
893
-				if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
894
-					throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
895
-				}
896
-
897
-				if (!($share->getNode() instanceof \OCP\Files\Folder)) {
898
-					throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders'));
899
-				}
900
-
901
-				// normalize to correct public upload permissions
902
-				$newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
903
-			}
904
-
905
-			if ($newPermissions !== null) {
906
-				$share->setPermissions($newPermissions);
907
-				$permissions = $newPermissions;
908
-			}
909
-
910
-			if ($expireDate === '') {
911
-				$share->setExpirationDate(null);
912
-			} else if ($expireDate !== null) {
913
-				try {
914
-					$expireDate = $this->parseDate($expireDate);
915
-				} catch (\Exception $e) {
916
-					throw new OCSBadRequestException($e->getMessage(), $e);
917
-				}
918
-				$share->setExpirationDate($expireDate);
919
-			}
920
-
921
-			if ($password === '') {
922
-				$share->setPassword(null);
923
-			} else if ($password !== null) {
924
-				$share->setPassword($password);
925
-			}
926
-
927
-			if ($label !== null) {
928
-				$share->setLabel($label);
929
-			}
930
-
931
-			if ($sendPasswordByTalk === 'true') {
932
-				if (!$this->appManager->isEnabledForUser('spreed')) {
933
-					throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
934
-				}
935
-
936
-				$share->setSendPasswordByTalk(true);
937
-			} else if ($sendPasswordByTalk !== null) {
938
-				$share->setSendPasswordByTalk(false);
939
-			}
940
-		} else {
941
-			if ($permissions !== null) {
942
-				$permissions = (int)$permissions;
943
-				$share->setPermissions($permissions);
944
-			}
945
-
946
-			if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
947
-				if ($password === '') {
948
-					$share->setPassword(null);
949
-				} else if ($password !== null) {
950
-					$share->setPassword($password);
951
-				}
952
-
953
-				if ($sendPasswordByTalk === 'true') {
954
-					if (!$this->appManager->isEnabledForUser('spreed')) {
955
-						throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
956
-					}
957
-
958
-					$share->setSendPasswordByTalk(true);
959
-				} else {
960
-					$share->setSendPasswordByTalk(false);
961
-				}
962
-			}
963
-
964
-			if ($expireDate === '') {
965
-				$share->setExpirationDate(null);
966
-			} else if ($expireDate !== null) {
967
-				try {
968
-					$expireDate = $this->parseDate($expireDate);
969
-				} catch (\Exception $e) {
970
-					throw new OCSBadRequestException($e->getMessage(), $e);
971
-				}
972
-				$share->setExpirationDate($expireDate);
973
-			}
974
-
975
-		}
976
-
977
-		if ($permissions !== null && $share->getShareOwner() !== $this->currentUser) {
978
-
979
-			// Get the root mount point for the user and check the share permissions there
980
-			$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
981
-			$userNodes = $userFolder->getById($share->getNodeId());
982
-			$userNode = array_shift($userNodes);
983
-
984
-			$userMountPointId = $userNode->getMountPoint()->getStorageRootId();
985
-			$userMountPoints = $userFolder->getById($userMountPointId);
986
-			$userMountPoint = array_shift($userMountPoints);
987
-
988
-			/* Check if this is an incoming share */
989
-			$incomingShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $userMountPoint, -1, 0);
990
-			$incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $userMountPoint, -1, 0));
991
-			$incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $userMountPoint, -1, 0));
992
-
993
-			/** @var \OCP\Share\IShare[] $incomingShares */
994
-			if (!empty($incomingShares)) {
995
-				$maxPermissions = 0;
996
-				foreach ($incomingShares as $incomingShare) {
997
-					$maxPermissions |= $incomingShare->getPermissions();
998
-				}
999
-
1000
-				if ($share->getPermissions() & ~$maxPermissions) {
1001
-					throw new OCSNotFoundException($this->l->t('Cannot increase permissions'));
1002
-				}
1003
-			}
1004
-		}
1005
-
1006
-
1007
-		try {
1008
-			$share = $this->shareManager->updateShare($share);
1009
-		} catch (\Exception $e) {
1010
-			throw new OCSBadRequestException($e->getMessage(), $e);
1011
-		}
1012
-
1013
-		return new DataResponse($this->formatShare($share));
1014
-	}
1015
-
1016
-	/**
1017
-	 * @suppress PhanUndeclaredClassMethod
1018
-	 */
1019
-	protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups = true): bool {
1020
-		// A file with permissions 0 can't be accessed by us. So Don't show it
1021
-		if ($share->getPermissions() === 0) {
1022
-			return false;
1023
-		}
1024
-
1025
-		// Owner of the file and the sharer of the file can always get share
1026
-		if ($share->getShareOwner() === $this->currentUser ||
1027
-			$share->getSharedBy() === $this->currentUser
1028
-		) {
1029
-			return true;
1030
-		}
1031
-
1032
-		// If the share is shared with you (or a group you are a member of)
1033
-		if ($share->getShareType() === Share::SHARE_TYPE_USER &&
1034
-			$share->getSharedWith() === $this->currentUser
1035
-		) {
1036
-			return true;
1037
-		}
1038
-
1039
-		if ($checkGroups && $share->getShareType() === Share::SHARE_TYPE_GROUP) {
1040
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
1041
-			$user = $this->userManager->get($this->currentUser);
1042
-			if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
1043
-				return true;
1044
-			}
1045
-		}
1046
-
1047
-		if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
1048
-			// TODO: have a sanity check like above?
1049
-			return true;
1050
-		}
1051
-
1052
-		if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
1053
-			try {
1054
-				return $this->getRoomShareHelper()->canAccessShare($share, $this->currentUser);
1055
-			} catch (QueryException $e) {
1056
-				return false;
1057
-			}
1058
-		}
1059
-
1060
-		return false;
1061
-	}
1062
-
1063
-	/**
1064
-	 * Make sure that the passed date is valid ISO 8601
1065
-	 * So YYYY-MM-DD
1066
-	 * If not throw an exception
1067
-	 *
1068
-	 * @param string $expireDate
1069
-	 *
1070
-	 * @throws \Exception
1071
-	 * @return \DateTime
1072
-	 */
1073
-	private function parseDate(string $expireDate): \DateTime {
1074
-		try {
1075
-			$date = new \DateTime($expireDate);
1076
-		} catch (\Exception $e) {
1077
-			throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
1078
-		}
1079
-
1080
-		if ($date === false) {
1081
-			throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
1082
-		}
1083
-
1084
-		$date->setTime(0, 0, 0);
1085
-
1086
-		return $date;
1087
-	}
1088
-
1089
-	/**
1090
-	 * Since we have multiple providers but the OCS Share API v1 does
1091
-	 * not support this we need to check all backends.
1092
-	 *
1093
-	 * @param string $id
1094
-	 * @return \OCP\Share\IShare
1095
-	 * @throws ShareNotFound
1096
-	 */
1097
-	private function getShareById(string $id): IShare {
1098
-		$share = null;
1099
-
1100
-		// First check if it is an internal share.
1101
-		try {
1102
-			$share = $this->shareManager->getShareById('ocinternal:' . $id, $this->currentUser);
1103
-			return $share;
1104
-		} catch (ShareNotFound $e) {
1105
-			// Do nothing, just try the other share type
1106
-		}
1107
-
1108
-
1109
-		try {
1110
-			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
1111
-				$share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->currentUser);
1112
-				return $share;
1113
-			}
1114
-		} catch (ShareNotFound $e) {
1115
-			// Do nothing, just try the other share type
1116
-		}
1117
-
1118
-		try {
1119
-			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
1120
-				$share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->currentUser);
1121
-				return $share;
1122
-			}
1123
-		} catch (ShareNotFound $e) {
1124
-			// Do nothing, just try the other share type
1125
-		}
1126
-
1127
-		try {
1128
-			$share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->currentUser);
1129
-			return $share;
1130
-		} catch (ShareNotFound $e) {
1131
-			// Do nothing, just try the other share type
1132
-		}
1133
-
1134
-		if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
1135
-			throw new ShareNotFound();
1136
-		}
1137
-		$share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $this->currentUser);
1138
-
1139
-		return $share;
1140
-	}
1141
-
1142
-	/**
1143
-	 * Lock a Node
1144
-	 *
1145
-	 * @param \OCP\Files\Node $node
1146
-	 * @throws LockedException
1147
-	 */
1148
-	private function lock(\OCP\Files\Node $node) {
1149
-		$node->lock(ILockingProvider::LOCK_SHARED);
1150
-		$this->lockedNode = $node;
1151
-	}
1152
-
1153
-	/**
1154
-	 * Cleanup the remaining locks
1155
-	 * @throws @LockedException
1156
-	 */
1157
-	public function cleanup() {
1158
-		if ($this->lockedNode !== null) {
1159
-			$this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
1160
-		}
1161
-	}
1162
-
1163
-	/**
1164
-	 * Returns the helper of ShareAPIController for room shares.
1165
-	 *
1166
-	 * If the Talk application is not enabled or the helper is not available
1167
-	 * a QueryException is thrown instead.
1168
-	 *
1169
-	 * @return \OCA\Spreed\Share\Helper\ShareAPIController
1170
-	 * @throws QueryException
1171
-	 */
1172
-	private function getRoomShareHelper() {
1173
-		if (!$this->appManager->isEnabledForUser('spreed')) {
1174
-			throw new QueryException();
1175
-		}
1176
-
1177
-		return $this->serverContainer->query('\OCA\Spreed\Share\Helper\ShareAPIController');
1178
-	}
1179
-
1180
-
1181
-	/**
1182
-	 * Returns if we can find resharing rights in an IShare object for a specific user.
1183
-	 *
1184
-	 * @suppress PhanUndeclaredClassMethod
1185
-	 *
1186
-	 * @param string $userId
1187
-	 * @param IShare $share
1188
-	 * @param Node $node
1189
-	 * @return bool
1190
-	 * @throws NotFoundException
1191
-	 * @throws \OCP\Files\InvalidPathException
1192
-	 */
1193
-	private function shareProviderResharingRights(string $userId, IShare $share, $node): bool {
1194
-
1195
-		if ($share->getShareOwner() === $userId) {
1196
-			return true;
1197
-		}
1198
-
1199
-		// we check that current user have parent resharing rights on the current file
1200
-		if ($node !== null && ($node->getPermissions() & \OCP\Constants::PERMISSION_SHARE) !== 0) {
1201
-			return true;
1202
-		}
1203
-
1204
-		if ((\OCP\Constants::PERMISSION_SHARE & $share->getPermissions()) === 0) {
1205
-			return false;
1206
-		}
1207
-
1208
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() === $userId) {
1209
-			return true;
1210
-		}
1211
-
1212
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && $this->groupManager->isInGroup($userId, $share->getSharedWith())) {
1213
-			return true;
1214
-		}
1215
-
1216
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE && \OC::$server->getAppManager()->isEnabledForUser('circles') &&
1217
-			class_exists('\OCA\Circles\Api\v1\Circles')) {
1218
-			$hasCircleId = (substr($share->getSharedWith(), -1) === ']');
1219
-			$shareWithStart = ($hasCircleId ? strrpos($share->getSharedWith(), '[') + 1 : 0);
1220
-			$shareWithLength = ($hasCircleId ? -1 : strpos($share->getSharedWith(), ' '));
1221
-			if (is_bool($shareWithLength)) {
1222
-				$shareWithLength = -1;
1223
-			}
1224
-			$sharedWith = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
1225
-			try {
1226
-				$member = \OCA\Circles\Api\v1\Circles::getMember($sharedWith, $userId, 1);
1227
-				if ($member->getLevel() >= 4) {
1228
-					return true;
1229
-				}
1230
-				return false;
1231
-			} catch (QueryException $e) {
1232
-				return false;
1233
-			}
1234
-		}
1235
-
1236
-		return false;
1237
-	}
854
+        if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
855
+
856
+            // Update hide download state
857
+            if ($hideDownload === 'true') {
858
+                $share->setHideDownload(true);
859
+            } else if ($hideDownload === 'false') {
860
+                $share->setHideDownload(false);
861
+            }
862
+
863
+            $newPermissions = null;
864
+            if ($publicUpload === 'true') {
865
+                $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
866
+            } else if ($publicUpload === 'false') {
867
+                $newPermissions = Constants::PERMISSION_READ;
868
+            }
869
+
870
+            if ($permissions !== null) {
871
+                $newPermissions = (int)$permissions;
872
+                $newPermissions = $newPermissions & ~Constants::PERMISSION_SHARE;
873
+            }
874
+
875
+            if ($newPermissions !== null &&
876
+                !in_array($newPermissions, [
877
+                    Constants::PERMISSION_READ,
878
+                    Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE, // legacy
879
+                    Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE, // correct
880
+                    Constants::PERMISSION_CREATE, // hidden file list
881
+                    Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE, // allow to edit single files
882
+                ], true)
883
+            ) {
884
+                throw new OCSBadRequestException($this->l->t('Can\'t change permissions for public share links'));
885
+            }
886
+
887
+            if (
888
+                // legacy
889
+                $newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE) ||
890
+                // correct
891
+                $newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
892
+            ) {
893
+                if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
894
+                    throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
895
+                }
896
+
897
+                if (!($share->getNode() instanceof \OCP\Files\Folder)) {
898
+                    throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders'));
899
+                }
900
+
901
+                // normalize to correct public upload permissions
902
+                $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
903
+            }
904
+
905
+            if ($newPermissions !== null) {
906
+                $share->setPermissions($newPermissions);
907
+                $permissions = $newPermissions;
908
+            }
909
+
910
+            if ($expireDate === '') {
911
+                $share->setExpirationDate(null);
912
+            } else if ($expireDate !== null) {
913
+                try {
914
+                    $expireDate = $this->parseDate($expireDate);
915
+                } catch (\Exception $e) {
916
+                    throw new OCSBadRequestException($e->getMessage(), $e);
917
+                }
918
+                $share->setExpirationDate($expireDate);
919
+            }
920
+
921
+            if ($password === '') {
922
+                $share->setPassword(null);
923
+            } else if ($password !== null) {
924
+                $share->setPassword($password);
925
+            }
926
+
927
+            if ($label !== null) {
928
+                $share->setLabel($label);
929
+            }
930
+
931
+            if ($sendPasswordByTalk === 'true') {
932
+                if (!$this->appManager->isEnabledForUser('spreed')) {
933
+                    throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
934
+                }
935
+
936
+                $share->setSendPasswordByTalk(true);
937
+            } else if ($sendPasswordByTalk !== null) {
938
+                $share->setSendPasswordByTalk(false);
939
+            }
940
+        } else {
941
+            if ($permissions !== null) {
942
+                $permissions = (int)$permissions;
943
+                $share->setPermissions($permissions);
944
+            }
945
+
946
+            if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
947
+                if ($password === '') {
948
+                    $share->setPassword(null);
949
+                } else if ($password !== null) {
950
+                    $share->setPassword($password);
951
+                }
952
+
953
+                if ($sendPasswordByTalk === 'true') {
954
+                    if (!$this->appManager->isEnabledForUser('spreed')) {
955
+                        throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
956
+                    }
957
+
958
+                    $share->setSendPasswordByTalk(true);
959
+                } else {
960
+                    $share->setSendPasswordByTalk(false);
961
+                }
962
+            }
963
+
964
+            if ($expireDate === '') {
965
+                $share->setExpirationDate(null);
966
+            } else if ($expireDate !== null) {
967
+                try {
968
+                    $expireDate = $this->parseDate($expireDate);
969
+                } catch (\Exception $e) {
970
+                    throw new OCSBadRequestException($e->getMessage(), $e);
971
+                }
972
+                $share->setExpirationDate($expireDate);
973
+            }
974
+
975
+        }
976
+
977
+        if ($permissions !== null && $share->getShareOwner() !== $this->currentUser) {
978
+
979
+            // Get the root mount point for the user and check the share permissions there
980
+            $userFolder = $this->rootFolder->getUserFolder($this->currentUser);
981
+            $userNodes = $userFolder->getById($share->getNodeId());
982
+            $userNode = array_shift($userNodes);
983
+
984
+            $userMountPointId = $userNode->getMountPoint()->getStorageRootId();
985
+            $userMountPoints = $userFolder->getById($userMountPointId);
986
+            $userMountPoint = array_shift($userMountPoints);
987
+
988
+            /* Check if this is an incoming share */
989
+            $incomingShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $userMountPoint, -1, 0);
990
+            $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $userMountPoint, -1, 0));
991
+            $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $userMountPoint, -1, 0));
992
+
993
+            /** @var \OCP\Share\IShare[] $incomingShares */
994
+            if (!empty($incomingShares)) {
995
+                $maxPermissions = 0;
996
+                foreach ($incomingShares as $incomingShare) {
997
+                    $maxPermissions |= $incomingShare->getPermissions();
998
+                }
999
+
1000
+                if ($share->getPermissions() & ~$maxPermissions) {
1001
+                    throw new OCSNotFoundException($this->l->t('Cannot increase permissions'));
1002
+                }
1003
+            }
1004
+        }
1005
+
1006
+
1007
+        try {
1008
+            $share = $this->shareManager->updateShare($share);
1009
+        } catch (\Exception $e) {
1010
+            throw new OCSBadRequestException($e->getMessage(), $e);
1011
+        }
1012
+
1013
+        return new DataResponse($this->formatShare($share));
1014
+    }
1015
+
1016
+    /**
1017
+     * @suppress PhanUndeclaredClassMethod
1018
+     */
1019
+    protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups = true): bool {
1020
+        // A file with permissions 0 can't be accessed by us. So Don't show it
1021
+        if ($share->getPermissions() === 0) {
1022
+            return false;
1023
+        }
1024
+
1025
+        // Owner of the file and the sharer of the file can always get share
1026
+        if ($share->getShareOwner() === $this->currentUser ||
1027
+            $share->getSharedBy() === $this->currentUser
1028
+        ) {
1029
+            return true;
1030
+        }
1031
+
1032
+        // If the share is shared with you (or a group you are a member of)
1033
+        if ($share->getShareType() === Share::SHARE_TYPE_USER &&
1034
+            $share->getSharedWith() === $this->currentUser
1035
+        ) {
1036
+            return true;
1037
+        }
1038
+
1039
+        if ($checkGroups && $share->getShareType() === Share::SHARE_TYPE_GROUP) {
1040
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
1041
+            $user = $this->userManager->get($this->currentUser);
1042
+            if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
1043
+                return true;
1044
+            }
1045
+        }
1046
+
1047
+        if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
1048
+            // TODO: have a sanity check like above?
1049
+            return true;
1050
+        }
1051
+
1052
+        if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
1053
+            try {
1054
+                return $this->getRoomShareHelper()->canAccessShare($share, $this->currentUser);
1055
+            } catch (QueryException $e) {
1056
+                return false;
1057
+            }
1058
+        }
1059
+
1060
+        return false;
1061
+    }
1062
+
1063
+    /**
1064
+     * Make sure that the passed date is valid ISO 8601
1065
+     * So YYYY-MM-DD
1066
+     * If not throw an exception
1067
+     *
1068
+     * @param string $expireDate
1069
+     *
1070
+     * @throws \Exception
1071
+     * @return \DateTime
1072
+     */
1073
+    private function parseDate(string $expireDate): \DateTime {
1074
+        try {
1075
+            $date = new \DateTime($expireDate);
1076
+        } catch (\Exception $e) {
1077
+            throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
1078
+        }
1079
+
1080
+        if ($date === false) {
1081
+            throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
1082
+        }
1083
+
1084
+        $date->setTime(0, 0, 0);
1085
+
1086
+        return $date;
1087
+    }
1088
+
1089
+    /**
1090
+     * Since we have multiple providers but the OCS Share API v1 does
1091
+     * not support this we need to check all backends.
1092
+     *
1093
+     * @param string $id
1094
+     * @return \OCP\Share\IShare
1095
+     * @throws ShareNotFound
1096
+     */
1097
+    private function getShareById(string $id): IShare {
1098
+        $share = null;
1099
+
1100
+        // First check if it is an internal share.
1101
+        try {
1102
+            $share = $this->shareManager->getShareById('ocinternal:' . $id, $this->currentUser);
1103
+            return $share;
1104
+        } catch (ShareNotFound $e) {
1105
+            // Do nothing, just try the other share type
1106
+        }
1107
+
1108
+
1109
+        try {
1110
+            if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
1111
+                $share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->currentUser);
1112
+                return $share;
1113
+            }
1114
+        } catch (ShareNotFound $e) {
1115
+            // Do nothing, just try the other share type
1116
+        }
1117
+
1118
+        try {
1119
+            if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
1120
+                $share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->currentUser);
1121
+                return $share;
1122
+            }
1123
+        } catch (ShareNotFound $e) {
1124
+            // Do nothing, just try the other share type
1125
+        }
1126
+
1127
+        try {
1128
+            $share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->currentUser);
1129
+            return $share;
1130
+        } catch (ShareNotFound $e) {
1131
+            // Do nothing, just try the other share type
1132
+        }
1133
+
1134
+        if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
1135
+            throw new ShareNotFound();
1136
+        }
1137
+        $share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $this->currentUser);
1138
+
1139
+        return $share;
1140
+    }
1141
+
1142
+    /**
1143
+     * Lock a Node
1144
+     *
1145
+     * @param \OCP\Files\Node $node
1146
+     * @throws LockedException
1147
+     */
1148
+    private function lock(\OCP\Files\Node $node) {
1149
+        $node->lock(ILockingProvider::LOCK_SHARED);
1150
+        $this->lockedNode = $node;
1151
+    }
1152
+
1153
+    /**
1154
+     * Cleanup the remaining locks
1155
+     * @throws @LockedException
1156
+     */
1157
+    public function cleanup() {
1158
+        if ($this->lockedNode !== null) {
1159
+            $this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
1160
+        }
1161
+    }
1162
+
1163
+    /**
1164
+     * Returns the helper of ShareAPIController for room shares.
1165
+     *
1166
+     * If the Talk application is not enabled or the helper is not available
1167
+     * a QueryException is thrown instead.
1168
+     *
1169
+     * @return \OCA\Spreed\Share\Helper\ShareAPIController
1170
+     * @throws QueryException
1171
+     */
1172
+    private function getRoomShareHelper() {
1173
+        if (!$this->appManager->isEnabledForUser('spreed')) {
1174
+            throw new QueryException();
1175
+        }
1176
+
1177
+        return $this->serverContainer->query('\OCA\Spreed\Share\Helper\ShareAPIController');
1178
+    }
1179
+
1180
+
1181
+    /**
1182
+     * Returns if we can find resharing rights in an IShare object for a specific user.
1183
+     *
1184
+     * @suppress PhanUndeclaredClassMethod
1185
+     *
1186
+     * @param string $userId
1187
+     * @param IShare $share
1188
+     * @param Node $node
1189
+     * @return bool
1190
+     * @throws NotFoundException
1191
+     * @throws \OCP\Files\InvalidPathException
1192
+     */
1193
+    private function shareProviderResharingRights(string $userId, IShare $share, $node): bool {
1194
+
1195
+        if ($share->getShareOwner() === $userId) {
1196
+            return true;
1197
+        }
1198
+
1199
+        // we check that current user have parent resharing rights on the current file
1200
+        if ($node !== null && ($node->getPermissions() & \OCP\Constants::PERMISSION_SHARE) !== 0) {
1201
+            return true;
1202
+        }
1203
+
1204
+        if ((\OCP\Constants::PERMISSION_SHARE & $share->getPermissions()) === 0) {
1205
+            return false;
1206
+        }
1207
+
1208
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() === $userId) {
1209
+            return true;
1210
+        }
1211
+
1212
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && $this->groupManager->isInGroup($userId, $share->getSharedWith())) {
1213
+            return true;
1214
+        }
1215
+
1216
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE && \OC::$server->getAppManager()->isEnabledForUser('circles') &&
1217
+            class_exists('\OCA\Circles\Api\v1\Circles')) {
1218
+            $hasCircleId = (substr($share->getSharedWith(), -1) === ']');
1219
+            $shareWithStart = ($hasCircleId ? strrpos($share->getSharedWith(), '[') + 1 : 0);
1220
+            $shareWithLength = ($hasCircleId ? -1 : strpos($share->getSharedWith(), ' '));
1221
+            if (is_bool($shareWithLength)) {
1222
+                $shareWithLength = -1;
1223
+            }
1224
+            $sharedWith = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
1225
+            try {
1226
+                $member = \OCA\Circles\Api\v1\Circles::getMember($sharedWith, $userId, 1);
1227
+                if ($member->getLevel() >= 4) {
1228
+                    return true;
1229
+                }
1230
+                return false;
1231
+            } catch (QueryException $e) {
1232
+                return false;
1233
+            }
1234
+        }
1235
+
1236
+        return false;
1237
+    }
1238 1238
 
1239 1239
 }
Please login to merge, or discard this patch.