Passed
Push — master ( ab3543...7940a7 )
by Morris
69:04 queued 44:02
created
apps/files_sharing/lib/Controller/ShareAPIController.php 1 patch
Indentation   +1130 added lines, -1130 removed lines patch added patch discarded remove patch
@@ -65,1141 +65,1141 @@
 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
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $node, false, -1, 0));
631
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $node, false, -1, 0));
632
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $node, false, -1, 0));
633
-			if($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
634
-				$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $node, false, -1, 0));
635
-			}
636
-			if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
637
-				$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, false, -1, 0));
638
-			}
639
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $node, false, -1, 0));
640
-		}
641
-
642
-		$formatted = [];
643
-		foreach ($shares as $share) {
644
-			try {
645
-				$formatted[] = $this->formatShare($share);
646
-			} catch (NotFoundException $e) {
647
-				//Ignore this share
648
-			}
649
-		}
650
-
651
-		return new DataResponse($formatted);
652
-	}
653
-
654
-	/**
655
-	 * The getShares function.
656
-	 *
657
-	 * @NoAdminRequired
658
-	 *
659
-	 * @param string $shared_with_me
660
-	 * @param string $reshares
661
-	 * @param string $subfiles
662
-	 * @param string $path
663
-	 *
664
-	 * - Get shares by the current user
665
-	 * - Get shares by the current user and reshares (?reshares=true)
666
-	 * - Get shares with the current user (?shared_with_me=true)
667
-	 * - Get shares for a specific path (?path=...)
668
-	 * - Get all shares in a folder (?subfiles=true&path=..)
669
-	 *
670
-	 * @return DataResponse
671
-	 * @throws OCSNotFoundException
672
-	 */
673
-	public function getShares(
674
-		string $shared_with_me = 'false',
675
-		string $reshares = 'false',
676
-		string $subfiles = 'false',
677
-		string $path = null,
678
-		string $include_tags = 'false'
679
-	): DataResponse {
680
-
681
-		if ($path !== null) {
682
-			$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
683
-			try {
684
-				$path = $userFolder->get($path);
685
-				$this->lock($path);
686
-			} catch (\OCP\Files\NotFoundException $e) {
687
-				throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
688
-			} catch (LockedException $e) {
689
-				throw new OCSNotFoundException($this->l->t('Could not lock path'));
690
-			}
691
-		}
692
-
693
-		$include_tags = $include_tags === 'true';
694
-
695
-		if ($shared_with_me === 'true') {
696
-			$result = $this->getSharedWithMe($path, $include_tags);
697
-			return $result;
698
-		}
699
-
700
-		if ($subfiles === 'true') {
701
-			$result = $this->getSharesInDir($path);
702
-			return $result;
703
-		}
704
-
705
-		if ($reshares === 'true') {
706
-			$reshares = true;
707
-		} else {
708
-			$reshares = false;
709
-		}
710
-
711
-		// Get all shares
712
-		$userShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
713
-		$groupShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
714
-		$linkShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
715
-		if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
716
-			$mailShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0);
717
-		} else {
718
-			$mailShares = [];
719
-		}
720
-		if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
721
-			$circleShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0);
722
-		} else {
723
-			$circleShares = [];
724
-		}
725
-		$roomShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $path, $reshares, -1, 0);
726
-
727
-		$shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares);
728
-
729
-		if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
730
-			$federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
731
-			$shares = array_merge($shares, $federatedShares);
732
-		}
733
-
734
-		if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
735
-			$federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE_GROUP, $path, $reshares, -1, 0);
736
-			$shares = array_merge($shares, $federatedShares);
737
-		}
738
-
739
-		$formatted = $miniFormatted = [];
740
-		$resharingRight = false;
741
-		foreach ($shares as $share) {
742
-			/** @var IShare $share */
743
-			try {
744
-				$format = $this->formatShare($share, $path);
745
-				$formatted[] = $format;
746
-				if ($share->getSharedBy() === $this->currentUser) {
747
-					$miniFormatted[] = $format;
748
-				}
749
-
750
-				if (!$resharingRight && $this->shareProviderResharingRights($this->currentUser, $share, $path)) {
751
-					$resharingRight = true;
752
-				}
753
-			} catch (\Exception $e) {
754
-				//Ignore share
755
-			}
756
-		}
757
-
758
-		if (!$resharingRight) {
759
-			$formatted = $miniFormatted;
760
-		}
761
-
762
-		if ($include_tags) {
763
-			$formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
764
-		}
765
-
766
-		return new DataResponse($formatted);
767
-	}
768
-
769
-	/**
770
-	 * @NoAdminRequired
771
-	 *
772
-	 * @param string $id
773
-	 * @param int $permissions
774
-	 * @param string $password
775
-	 * @param string $sendPasswordByTalk
776
-	 * @param string $publicUpload
777
-	 * @param string $expireDate
778
-	 * @param string $note
779
-	 * @param string $label
780
-	 * @param string $hideDownload
781
-	 * @return DataResponse
782
-	 * @throws LockedException
783
-	 * @throws NotFoundException
784
-	 * @throws OCSBadRequestException
785
-	 * @throws OCSForbiddenException
786
-	 * @throws OCSNotFoundException
787
-	 */
788
-	public function updateShare(
789
-		string $id,
790
-		int $permissions = null,
791
-		string $password = null,
792
-		string $sendPasswordByTalk = null,
793
-		string $publicUpload = null,
794
-		string $expireDate = null,
795
-		string $note = null,
796
-		string $label = null,
797
-		string $hideDownload = null
798
-	): DataResponse {
799
-		try {
800
-			$share = $this->getShareById($id);
801
-		} catch (ShareNotFound $e) {
802
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
803
-		}
804
-
805
-		$this->lock($share->getNode());
806
-
807
-		if (!$this->canAccessShare($share, false)) {
808
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
809
-		}
810
-
811
-		if ($permissions === null &&
812
-			$password === null &&
813
-			$sendPasswordByTalk === null &&
814
-			$publicUpload === null &&
815
-			$expireDate === null &&
816
-			$note === null &&
817
-			$label === null &&
818
-			$hideDownload === null
819
-		) {
820
-			throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
821
-		}
822
-
823
-		if($note !== null) {
824
-			$share->setNote($note);
825
-		}
826
-
827
-		/*
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
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $node, false, -1, 0));
631
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $node, false, -1, 0));
632
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $node, false, -1, 0));
633
+            if($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
634
+                $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $node, false, -1, 0));
635
+            }
636
+            if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
637
+                $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, false, -1, 0));
638
+            }
639
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $node, false, -1, 0));
640
+        }
641
+
642
+        $formatted = [];
643
+        foreach ($shares as $share) {
644
+            try {
645
+                $formatted[] = $this->formatShare($share);
646
+            } catch (NotFoundException $e) {
647
+                //Ignore this share
648
+            }
649
+        }
650
+
651
+        return new DataResponse($formatted);
652
+    }
653
+
654
+    /**
655
+     * The getShares function.
656
+     *
657
+     * @NoAdminRequired
658
+     *
659
+     * @param string $shared_with_me
660
+     * @param string $reshares
661
+     * @param string $subfiles
662
+     * @param string $path
663
+     *
664
+     * - Get shares by the current user
665
+     * - Get shares by the current user and reshares (?reshares=true)
666
+     * - Get shares with the current user (?shared_with_me=true)
667
+     * - Get shares for a specific path (?path=...)
668
+     * - Get all shares in a folder (?subfiles=true&path=..)
669
+     *
670
+     * @return DataResponse
671
+     * @throws OCSNotFoundException
672
+     */
673
+    public function getShares(
674
+        string $shared_with_me = 'false',
675
+        string $reshares = 'false',
676
+        string $subfiles = 'false',
677
+        string $path = null,
678
+        string $include_tags = 'false'
679
+    ): DataResponse {
680
+
681
+        if ($path !== null) {
682
+            $userFolder = $this->rootFolder->getUserFolder($this->currentUser);
683
+            try {
684
+                $path = $userFolder->get($path);
685
+                $this->lock($path);
686
+            } catch (\OCP\Files\NotFoundException $e) {
687
+                throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
688
+            } catch (LockedException $e) {
689
+                throw new OCSNotFoundException($this->l->t('Could not lock path'));
690
+            }
691
+        }
692
+
693
+        $include_tags = $include_tags === 'true';
694
+
695
+        if ($shared_with_me === 'true') {
696
+            $result = $this->getSharedWithMe($path, $include_tags);
697
+            return $result;
698
+        }
699
+
700
+        if ($subfiles === 'true') {
701
+            $result = $this->getSharesInDir($path);
702
+            return $result;
703
+        }
704
+
705
+        if ($reshares === 'true') {
706
+            $reshares = true;
707
+        } else {
708
+            $reshares = false;
709
+        }
710
+
711
+        // Get all shares
712
+        $userShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
713
+        $groupShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
714
+        $linkShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
715
+        if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
716
+            $mailShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0);
717
+        } else {
718
+            $mailShares = [];
719
+        }
720
+        if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
721
+            $circleShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0);
722
+        } else {
723
+            $circleShares = [];
724
+        }
725
+        $roomShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $path, $reshares, -1, 0);
726
+
727
+        $shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares);
728
+
729
+        if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
730
+            $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
731
+            $shares = array_merge($shares, $federatedShares);
732
+        }
733
+
734
+        if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
735
+            $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE_GROUP, $path, $reshares, -1, 0);
736
+            $shares = array_merge($shares, $federatedShares);
737
+        }
738
+
739
+        $formatted = $miniFormatted = [];
740
+        $resharingRight = false;
741
+        foreach ($shares as $share) {
742
+            /** @var IShare $share */
743
+            try {
744
+                $format = $this->formatShare($share, $path);
745
+                $formatted[] = $format;
746
+                if ($share->getSharedBy() === $this->currentUser) {
747
+                    $miniFormatted[] = $format;
748
+                }
749
+
750
+                if (!$resharingRight && $this->shareProviderResharingRights($this->currentUser, $share, $path)) {
751
+                    $resharingRight = true;
752
+                }
753
+            } catch (\Exception $e) {
754
+                //Ignore share
755
+            }
756
+        }
757
+
758
+        if (!$resharingRight) {
759
+            $formatted = $miniFormatted;
760
+        }
761
+
762
+        if ($include_tags) {
763
+            $formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
764
+        }
765
+
766
+        return new DataResponse($formatted);
767
+    }
768
+
769
+    /**
770
+     * @NoAdminRequired
771
+     *
772
+     * @param string $id
773
+     * @param int $permissions
774
+     * @param string $password
775
+     * @param string $sendPasswordByTalk
776
+     * @param string $publicUpload
777
+     * @param string $expireDate
778
+     * @param string $note
779
+     * @param string $label
780
+     * @param string $hideDownload
781
+     * @return DataResponse
782
+     * @throws LockedException
783
+     * @throws NotFoundException
784
+     * @throws OCSBadRequestException
785
+     * @throws OCSForbiddenException
786
+     * @throws OCSNotFoundException
787
+     */
788
+    public function updateShare(
789
+        string $id,
790
+        int $permissions = null,
791
+        string $password = null,
792
+        string $sendPasswordByTalk = null,
793
+        string $publicUpload = null,
794
+        string $expireDate = null,
795
+        string $note = null,
796
+        string $label = null,
797
+        string $hideDownload = null
798
+    ): DataResponse {
799
+        try {
800
+            $share = $this->getShareById($id);
801
+        } catch (ShareNotFound $e) {
802
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
803
+        }
804
+
805
+        $this->lock($share->getNode());
806
+
807
+        if (!$this->canAccessShare($share, false)) {
808
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
809
+        }
810
+
811
+        if ($permissions === null &&
812
+            $password === null &&
813
+            $sendPasswordByTalk === null &&
814
+            $publicUpload === null &&
815
+            $expireDate === null &&
816
+            $note === null &&
817
+            $label === null &&
818
+            $hideDownload === null
819
+        ) {
820
+            throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
821
+        }
822
+
823
+        if($note !== null) {
824
+            $share->setNote($note);
825
+        }
826
+
827
+        /*
828 828
 		 * expirationdate, password and publicUpload only make sense for link shares
829 829
 		 */
830
-		if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
831
-
832
-			// Update hide download state
833
-			if ($hideDownload === 'true') {
834
-				$share->setHideDownload(true);
835
-			} else if ($hideDownload === 'false') {
836
-				$share->setHideDownload(false);
837
-			}
838
-
839
-			$newPermissions = null;
840
-			if ($publicUpload === 'true') {
841
-				$newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
842
-			} else if ($publicUpload === 'false') {
843
-				$newPermissions = Constants::PERMISSION_READ;
844
-			}
845
-
846
-			if ($permissions !== null) {
847
-				$newPermissions = (int)$permissions;
848
-				$newPermissions = $newPermissions & ~Constants::PERMISSION_SHARE;
849
-			}
850
-
851
-			if ($newPermissions !== null &&
852
-				!in_array($newPermissions, [
853
-					Constants::PERMISSION_READ,
854
-					Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE, // legacy
855
-					Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE, // correct
856
-					Constants::PERMISSION_CREATE, // hidden file list
857
-					Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE, // allow to edit single files
858
-				], true)
859
-			) {
860
-				throw new OCSBadRequestException($this->l->t('Can\'t change permissions for public share links'));
861
-			}
862
-
863
-			if (
864
-				// legacy
865
-				$newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE) ||
866
-				// correct
867
-				$newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
868
-			) {
869
-				if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
870
-					throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
871
-				}
872
-
873
-				if (!($share->getNode() instanceof \OCP\Files\Folder)) {
874
-					throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders'));
875
-				}
876
-
877
-				// normalize to correct public upload permissions
878
-				$newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
879
-			}
880
-
881
-			if ($newPermissions !== null) {
882
-				$share->setPermissions($newPermissions);
883
-				$permissions = $newPermissions;
884
-			}
885
-
886
-			if ($expireDate === '') {
887
-				$share->setExpirationDate(null);
888
-			} else if ($expireDate !== null) {
889
-				try {
890
-					$expireDate = $this->parseDate($expireDate);
891
-				} catch (\Exception $e) {
892
-					throw new OCSBadRequestException($e->getMessage(), $e);
893
-				}
894
-				$share->setExpirationDate($expireDate);
895
-			}
896
-
897
-			if ($password === '') {
898
-				$share->setPassword(null);
899
-			} else if ($password !== null) {
900
-				$share->setPassword($password);
901
-			}
902
-
903
-			if ($label !== null) {
904
-				$share->setLabel($label);
905
-			}
906
-
907
-			if ($sendPasswordByTalk === 'true') {
908
-				if (!$this->appManager->isEnabledForUser('spreed')) {
909
-					throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
910
-				}
911
-
912
-				$share->setSendPasswordByTalk(true);
913
-			} else if ($sendPasswordByTalk !== null) {
914
-				$share->setSendPasswordByTalk(false);
915
-			}
916
-		} else {
917
-			if ($permissions !== null) {
918
-				$permissions = (int)$permissions;
919
-				$share->setPermissions($permissions);
920
-			}
921
-
922
-			if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
923
-				if ($password === '') {
924
-					$share->setPassword(null);
925
-				} else if ($password !== null) {
926
-					$share->setPassword($password);
927
-				}
928
-
929
-				if ($sendPasswordByTalk === 'true') {
930
-					if (!$this->appManager->isEnabledForUser('spreed')) {
931
-						throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
932
-					}
933
-
934
-					$share->setSendPasswordByTalk(true);
935
-				} else {
936
-					$share->setSendPasswordByTalk(false);
937
-				}
938
-			}
939
-
940
-			if ($expireDate === '') {
941
-				$share->setExpirationDate(null);
942
-			} else if ($expireDate !== null) {
943
-				try {
944
-					$expireDate = $this->parseDate($expireDate);
945
-				} catch (\Exception $e) {
946
-					throw new OCSBadRequestException($e->getMessage(), $e);
947
-				}
948
-				$share->setExpirationDate($expireDate);
949
-			}
950
-
951
-		}
952
-
953
-		if ($permissions !== null && $share->getShareOwner() !== $this->currentUser) {
954
-			/* Check if this is an incomming share */
955
-			$incomingShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $share->getNode(), -1, 0);
956
-			$incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0));
957
-			$incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0));
958
-
959
-			/** @var \OCP\Share\IShare[] $incomingShares */
960
-			if (!empty($incomingShares)) {
961
-				$maxPermissions = 0;
962
-				foreach ($incomingShares as $incomingShare) {
963
-					$maxPermissions |= $incomingShare->getPermissions();
964
-				}
965
-
966
-				if ($share->getPermissions() & ~$maxPermissions) {
967
-					throw new OCSNotFoundException($this->l->t('Cannot increase permissions'));
968
-				}
969
-			}
970
-		}
971
-
972
-
973
-		try {
974
-			$share = $this->shareManager->updateShare($share);
975
-		} catch (\Exception $e) {
976
-			throw new OCSBadRequestException($e->getMessage(), $e);
977
-		}
978
-
979
-		return new DataResponse($this->formatShare($share));
980
-	}
981
-
982
-	/**
983
-	 * @suppress PhanUndeclaredClassMethod
984
-	 */
985
-	protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups = true): bool {
986
-		// A file with permissions 0 can't be accessed by us. So Don't show it
987
-		if ($share->getPermissions() === 0) {
988
-			return false;
989
-		}
990
-
991
-		// Owner of the file and the sharer of the file can always get share
992
-		if ($share->getShareOwner() === $this->currentUser ||
993
-			$share->getSharedBy() === $this->currentUser
994
-		) {
995
-			return true;
996
-		}
997
-
998
-		// If the share is shared with you (or a group you are a member of)
999
-		if ($share->getShareType() === Share::SHARE_TYPE_USER &&
1000
-			$share->getSharedWith() === $this->currentUser
1001
-		) {
1002
-			return true;
1003
-		}
1004
-
1005
-		if ($checkGroups && $share->getShareType() === Share::SHARE_TYPE_GROUP) {
1006
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
1007
-			$user = $this->userManager->get($this->currentUser);
1008
-			if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
1009
-				return true;
1010
-			}
1011
-		}
1012
-
1013
-		if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
1014
-			// TODO: have a sanity check like above?
1015
-			return true;
1016
-		}
1017
-
1018
-		if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
1019
-			try {
1020
-				return $this->getRoomShareHelper()->canAccessShare($share, $this->currentUser);
1021
-			} catch (QueryException $e) {
1022
-				return false;
1023
-			}
1024
-		}
1025
-
1026
-		return false;
1027
-	}
1028
-
1029
-	/**
1030
-	 * Make sure that the passed date is valid ISO 8601
1031
-	 * So YYYY-MM-DD
1032
-	 * If not throw an exception
1033
-	 *
1034
-	 * @param string $expireDate
1035
-	 *
1036
-	 * @throws \Exception
1037
-	 * @return \DateTime
1038
-	 */
1039
-	private function parseDate(string $expireDate): \DateTime {
1040
-		try {
1041
-			$date = new \DateTime($expireDate);
1042
-		} catch (\Exception $e) {
1043
-			throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
1044
-		}
1045
-
1046
-		if ($date === false) {
1047
-			throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
1048
-		}
1049
-
1050
-		$date->setTime(0, 0, 0);
1051
-
1052
-		return $date;
1053
-	}
1054
-
1055
-	/**
1056
-	 * Since we have multiple providers but the OCS Share API v1 does
1057
-	 * not support this we need to check all backends.
1058
-	 *
1059
-	 * @param string $id
1060
-	 * @return \OCP\Share\IShare
1061
-	 * @throws ShareNotFound
1062
-	 */
1063
-	private function getShareById(string $id): IShare {
1064
-		$share = null;
1065
-
1066
-		// First check if it is an internal share.
1067
-		try {
1068
-			$share = $this->shareManager->getShareById('ocinternal:' . $id, $this->currentUser);
1069
-			return $share;
1070
-		} catch (ShareNotFound $e) {
1071
-			// Do nothing, just try the other share type
1072
-		}
1073
-
1074
-
1075
-		try {
1076
-			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
1077
-				$share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->currentUser);
1078
-				return $share;
1079
-			}
1080
-		} catch (ShareNotFound $e) {
1081
-			// Do nothing, just try the other share type
1082
-		}
1083
-
1084
-		try {
1085
-			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
1086
-				$share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->currentUser);
1087
-				return $share;
1088
-			}
1089
-		} catch (ShareNotFound $e) {
1090
-			// Do nothing, just try the other share type
1091
-		}
1092
-
1093
-		try {
1094
-			$share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->currentUser);
1095
-			return $share;
1096
-		} catch (ShareNotFound $e) {
1097
-			// Do nothing, just try the other share type
1098
-		}
1099
-
1100
-		if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
1101
-			throw new ShareNotFound();
1102
-		}
1103
-		$share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $this->currentUser);
1104
-
1105
-		return $share;
1106
-	}
1107
-
1108
-	/**
1109
-	 * Lock a Node
1110
-	 *
1111
-	 * @param \OCP\Files\Node $node
1112
-	 * @throws LockedException
1113
-	 */
1114
-	private function lock(\OCP\Files\Node $node) {
1115
-		$node->lock(ILockingProvider::LOCK_SHARED);
1116
-		$this->lockedNode = $node;
1117
-	}
1118
-
1119
-	/**
1120
-	 * Cleanup the remaining locks
1121
-	 * @throws @LockedException
1122
-	 */
1123
-	public function cleanup() {
1124
-		if ($this->lockedNode !== null) {
1125
-			$this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
1126
-		}
1127
-	}
1128
-
1129
-	/**
1130
-	 * Returns the helper of ShareAPIController for room shares.
1131
-	 *
1132
-	 * If the Talk application is not enabled or the helper is not available
1133
-	 * a QueryException is thrown instead.
1134
-	 *
1135
-	 * @return \OCA\Spreed\Share\Helper\ShareAPIController
1136
-	 * @throws QueryException
1137
-	 */
1138
-	private function getRoomShareHelper() {
1139
-		if (!$this->appManager->isEnabledForUser('spreed')) {
1140
-			throw new QueryException();
1141
-		}
1142
-
1143
-		return $this->serverContainer->query('\OCA\Spreed\Share\Helper\ShareAPIController');
1144
-	}
1145
-
1146
-
1147
-	/**
1148
-	 * Returns if we can find resharing rights in an IShare object for a specific user.
1149
-	 *
1150
-	 * @suppress PhanUndeclaredClassMethod
1151
-	 *
1152
-	 * @param string $userId
1153
-	 * @param IShare $share
1154
-	 * @param Node $node
1155
-	 * @return bool
1156
-	 * @throws NotFoundException
1157
-	 * @throws \OCP\Files\InvalidPathException
1158
-	 */
1159
-	private function shareProviderResharingRights(string $userId, IShare $share, $node): bool {
1160
-
1161
-		if ($share->getShareOwner() === $userId) {
1162
-			return true;
1163
-		}
1164
-
1165
-		// we check that current user have parent resharing rights on the current file
1166
-		if ($node !== null && ($node->getPermissions() & \OCP\Constants::PERMISSION_SHARE) !== 0) {
1167
-			return true;
1168
-		}
1169
-
1170
-		if ((\OCP\Constants::PERMISSION_SHARE & $share->getPermissions()) === 0) {
1171
-			return false;
1172
-		}
1173
-
1174
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() === $userId) {
1175
-			return true;
1176
-		}
1177
-
1178
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && $this->groupManager->isInGroup($userId, $share->getSharedWith())) {
1179
-			return true;
1180
-		}
1181
-
1182
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE && \OC::$server->getAppManager()->isEnabledForUser('circles') &&
1183
-			class_exists('\OCA\Circles\Api\v1\Circles')) {
1184
-			$hasCircleId = (substr($share->getSharedWith(), -1) === ']');
1185
-			$shareWithStart = ($hasCircleId ? strrpos($share->getSharedWith(), '[') + 1 : 0);
1186
-			$shareWithLength = ($hasCircleId ? -1 : strpos($share->getSharedWith(), ' '));
1187
-			if (is_bool($shareWithLength)) {
1188
-				$shareWithLength = -1;
1189
-			}
1190
-			$sharedWith = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
1191
-			try {
1192
-				$member = \OCA\Circles\Api\v1\Circles::getMember($sharedWith, $userId, 1);
1193
-				if ($member->getLevel() >= 4) {
1194
-					return true;
1195
-				}
1196
-				return false;
1197
-			} catch (QueryException $e) {
1198
-				return false;
1199
-			}
1200
-		}
1201
-
1202
-		return false;
1203
-	}
830
+        if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
831
+
832
+            // Update hide download state
833
+            if ($hideDownload === 'true') {
834
+                $share->setHideDownload(true);
835
+            } else if ($hideDownload === 'false') {
836
+                $share->setHideDownload(false);
837
+            }
838
+
839
+            $newPermissions = null;
840
+            if ($publicUpload === 'true') {
841
+                $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
842
+            } else if ($publicUpload === 'false') {
843
+                $newPermissions = Constants::PERMISSION_READ;
844
+            }
845
+
846
+            if ($permissions !== null) {
847
+                $newPermissions = (int)$permissions;
848
+                $newPermissions = $newPermissions & ~Constants::PERMISSION_SHARE;
849
+            }
850
+
851
+            if ($newPermissions !== null &&
852
+                !in_array($newPermissions, [
853
+                    Constants::PERMISSION_READ,
854
+                    Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE, // legacy
855
+                    Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE, // correct
856
+                    Constants::PERMISSION_CREATE, // hidden file list
857
+                    Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE, // allow to edit single files
858
+                ], true)
859
+            ) {
860
+                throw new OCSBadRequestException($this->l->t('Can\'t change permissions for public share links'));
861
+            }
862
+
863
+            if (
864
+                // legacy
865
+                $newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE) ||
866
+                // correct
867
+                $newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
868
+            ) {
869
+                if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
870
+                    throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
871
+                }
872
+
873
+                if (!($share->getNode() instanceof \OCP\Files\Folder)) {
874
+                    throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders'));
875
+                }
876
+
877
+                // normalize to correct public upload permissions
878
+                $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
879
+            }
880
+
881
+            if ($newPermissions !== null) {
882
+                $share->setPermissions($newPermissions);
883
+                $permissions = $newPermissions;
884
+            }
885
+
886
+            if ($expireDate === '') {
887
+                $share->setExpirationDate(null);
888
+            } else if ($expireDate !== null) {
889
+                try {
890
+                    $expireDate = $this->parseDate($expireDate);
891
+                } catch (\Exception $e) {
892
+                    throw new OCSBadRequestException($e->getMessage(), $e);
893
+                }
894
+                $share->setExpirationDate($expireDate);
895
+            }
896
+
897
+            if ($password === '') {
898
+                $share->setPassword(null);
899
+            } else if ($password !== null) {
900
+                $share->setPassword($password);
901
+            }
902
+
903
+            if ($label !== null) {
904
+                $share->setLabel($label);
905
+            }
906
+
907
+            if ($sendPasswordByTalk === 'true') {
908
+                if (!$this->appManager->isEnabledForUser('spreed')) {
909
+                    throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
910
+                }
911
+
912
+                $share->setSendPasswordByTalk(true);
913
+            } else if ($sendPasswordByTalk !== null) {
914
+                $share->setSendPasswordByTalk(false);
915
+            }
916
+        } else {
917
+            if ($permissions !== null) {
918
+                $permissions = (int)$permissions;
919
+                $share->setPermissions($permissions);
920
+            }
921
+
922
+            if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
923
+                if ($password === '') {
924
+                    $share->setPassword(null);
925
+                } else if ($password !== null) {
926
+                    $share->setPassword($password);
927
+                }
928
+
929
+                if ($sendPasswordByTalk === 'true') {
930
+                    if (!$this->appManager->isEnabledForUser('spreed')) {
931
+                        throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
932
+                    }
933
+
934
+                    $share->setSendPasswordByTalk(true);
935
+                } else {
936
+                    $share->setSendPasswordByTalk(false);
937
+                }
938
+            }
939
+
940
+            if ($expireDate === '') {
941
+                $share->setExpirationDate(null);
942
+            } else if ($expireDate !== null) {
943
+                try {
944
+                    $expireDate = $this->parseDate($expireDate);
945
+                } catch (\Exception $e) {
946
+                    throw new OCSBadRequestException($e->getMessage(), $e);
947
+                }
948
+                $share->setExpirationDate($expireDate);
949
+            }
950
+
951
+        }
952
+
953
+        if ($permissions !== null && $share->getShareOwner() !== $this->currentUser) {
954
+            /* Check if this is an incomming share */
955
+            $incomingShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $share->getNode(), -1, 0);
956
+            $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0));
957
+            $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0));
958
+
959
+            /** @var \OCP\Share\IShare[] $incomingShares */
960
+            if (!empty($incomingShares)) {
961
+                $maxPermissions = 0;
962
+                foreach ($incomingShares as $incomingShare) {
963
+                    $maxPermissions |= $incomingShare->getPermissions();
964
+                }
965
+
966
+                if ($share->getPermissions() & ~$maxPermissions) {
967
+                    throw new OCSNotFoundException($this->l->t('Cannot increase permissions'));
968
+                }
969
+            }
970
+        }
971
+
972
+
973
+        try {
974
+            $share = $this->shareManager->updateShare($share);
975
+        } catch (\Exception $e) {
976
+            throw new OCSBadRequestException($e->getMessage(), $e);
977
+        }
978
+
979
+        return new DataResponse($this->formatShare($share));
980
+    }
981
+
982
+    /**
983
+     * @suppress PhanUndeclaredClassMethod
984
+     */
985
+    protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups = true): bool {
986
+        // A file with permissions 0 can't be accessed by us. So Don't show it
987
+        if ($share->getPermissions() === 0) {
988
+            return false;
989
+        }
990
+
991
+        // Owner of the file and the sharer of the file can always get share
992
+        if ($share->getShareOwner() === $this->currentUser ||
993
+            $share->getSharedBy() === $this->currentUser
994
+        ) {
995
+            return true;
996
+        }
997
+
998
+        // If the share is shared with you (or a group you are a member of)
999
+        if ($share->getShareType() === Share::SHARE_TYPE_USER &&
1000
+            $share->getSharedWith() === $this->currentUser
1001
+        ) {
1002
+            return true;
1003
+        }
1004
+
1005
+        if ($checkGroups && $share->getShareType() === Share::SHARE_TYPE_GROUP) {
1006
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
1007
+            $user = $this->userManager->get($this->currentUser);
1008
+            if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
1009
+                return true;
1010
+            }
1011
+        }
1012
+
1013
+        if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
1014
+            // TODO: have a sanity check like above?
1015
+            return true;
1016
+        }
1017
+
1018
+        if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
1019
+            try {
1020
+                return $this->getRoomShareHelper()->canAccessShare($share, $this->currentUser);
1021
+            } catch (QueryException $e) {
1022
+                return false;
1023
+            }
1024
+        }
1025
+
1026
+        return false;
1027
+    }
1028
+
1029
+    /**
1030
+     * Make sure that the passed date is valid ISO 8601
1031
+     * So YYYY-MM-DD
1032
+     * If not throw an exception
1033
+     *
1034
+     * @param string $expireDate
1035
+     *
1036
+     * @throws \Exception
1037
+     * @return \DateTime
1038
+     */
1039
+    private function parseDate(string $expireDate): \DateTime {
1040
+        try {
1041
+            $date = new \DateTime($expireDate);
1042
+        } catch (\Exception $e) {
1043
+            throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
1044
+        }
1045
+
1046
+        if ($date === false) {
1047
+            throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
1048
+        }
1049
+
1050
+        $date->setTime(0, 0, 0);
1051
+
1052
+        return $date;
1053
+    }
1054
+
1055
+    /**
1056
+     * Since we have multiple providers but the OCS Share API v1 does
1057
+     * not support this we need to check all backends.
1058
+     *
1059
+     * @param string $id
1060
+     * @return \OCP\Share\IShare
1061
+     * @throws ShareNotFound
1062
+     */
1063
+    private function getShareById(string $id): IShare {
1064
+        $share = null;
1065
+
1066
+        // First check if it is an internal share.
1067
+        try {
1068
+            $share = $this->shareManager->getShareById('ocinternal:' . $id, $this->currentUser);
1069
+            return $share;
1070
+        } catch (ShareNotFound $e) {
1071
+            // Do nothing, just try the other share type
1072
+        }
1073
+
1074
+
1075
+        try {
1076
+            if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
1077
+                $share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->currentUser);
1078
+                return $share;
1079
+            }
1080
+        } catch (ShareNotFound $e) {
1081
+            // Do nothing, just try the other share type
1082
+        }
1083
+
1084
+        try {
1085
+            if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
1086
+                $share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->currentUser);
1087
+                return $share;
1088
+            }
1089
+        } catch (ShareNotFound $e) {
1090
+            // Do nothing, just try the other share type
1091
+        }
1092
+
1093
+        try {
1094
+            $share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->currentUser);
1095
+            return $share;
1096
+        } catch (ShareNotFound $e) {
1097
+            // Do nothing, just try the other share type
1098
+        }
1099
+
1100
+        if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
1101
+            throw new ShareNotFound();
1102
+        }
1103
+        $share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $this->currentUser);
1104
+
1105
+        return $share;
1106
+    }
1107
+
1108
+    /**
1109
+     * Lock a Node
1110
+     *
1111
+     * @param \OCP\Files\Node $node
1112
+     * @throws LockedException
1113
+     */
1114
+    private function lock(\OCP\Files\Node $node) {
1115
+        $node->lock(ILockingProvider::LOCK_SHARED);
1116
+        $this->lockedNode = $node;
1117
+    }
1118
+
1119
+    /**
1120
+     * Cleanup the remaining locks
1121
+     * @throws @LockedException
1122
+     */
1123
+    public function cleanup() {
1124
+        if ($this->lockedNode !== null) {
1125
+            $this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
1126
+        }
1127
+    }
1128
+
1129
+    /**
1130
+     * Returns the helper of ShareAPIController for room shares.
1131
+     *
1132
+     * If the Talk application is not enabled or the helper is not available
1133
+     * a QueryException is thrown instead.
1134
+     *
1135
+     * @return \OCA\Spreed\Share\Helper\ShareAPIController
1136
+     * @throws QueryException
1137
+     */
1138
+    private function getRoomShareHelper() {
1139
+        if (!$this->appManager->isEnabledForUser('spreed')) {
1140
+            throw new QueryException();
1141
+        }
1142
+
1143
+        return $this->serverContainer->query('\OCA\Spreed\Share\Helper\ShareAPIController');
1144
+    }
1145
+
1146
+
1147
+    /**
1148
+     * Returns if we can find resharing rights in an IShare object for a specific user.
1149
+     *
1150
+     * @suppress PhanUndeclaredClassMethod
1151
+     *
1152
+     * @param string $userId
1153
+     * @param IShare $share
1154
+     * @param Node $node
1155
+     * @return bool
1156
+     * @throws NotFoundException
1157
+     * @throws \OCP\Files\InvalidPathException
1158
+     */
1159
+    private function shareProviderResharingRights(string $userId, IShare $share, $node): bool {
1160
+
1161
+        if ($share->getShareOwner() === $userId) {
1162
+            return true;
1163
+        }
1164
+
1165
+        // we check that current user have parent resharing rights on the current file
1166
+        if ($node !== null && ($node->getPermissions() & \OCP\Constants::PERMISSION_SHARE) !== 0) {
1167
+            return true;
1168
+        }
1169
+
1170
+        if ((\OCP\Constants::PERMISSION_SHARE & $share->getPermissions()) === 0) {
1171
+            return false;
1172
+        }
1173
+
1174
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() === $userId) {
1175
+            return true;
1176
+        }
1177
+
1178
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && $this->groupManager->isInGroup($userId, $share->getSharedWith())) {
1179
+            return true;
1180
+        }
1181
+
1182
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE && \OC::$server->getAppManager()->isEnabledForUser('circles') &&
1183
+            class_exists('\OCA\Circles\Api\v1\Circles')) {
1184
+            $hasCircleId = (substr($share->getSharedWith(), -1) === ']');
1185
+            $shareWithStart = ($hasCircleId ? strrpos($share->getSharedWith(), '[') + 1 : 0);
1186
+            $shareWithLength = ($hasCircleId ? -1 : strpos($share->getSharedWith(), ' '));
1187
+            if (is_bool($shareWithLength)) {
1188
+                $shareWithLength = -1;
1189
+            }
1190
+            $sharedWith = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
1191
+            try {
1192
+                $member = \OCA\Circles\Api\v1\Circles::getMember($sharedWith, $userId, 1);
1193
+                if ($member->getLevel() >= 4) {
1194
+                    return true;
1195
+                }
1196
+                return false;
1197
+            } catch (QueryException $e) {
1198
+                return false;
1199
+            }
1200
+        }
1201
+
1202
+        return false;
1203
+    }
1204 1204
 
1205 1205
 }
Please login to merge, or discard this patch.