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