Completed
Push — master ( e4436e...70eef2 )
by Lukas
14:47
created

Share20OCS::getShareById()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 1
dl 0
loc 16
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 * @author Roeland Jago Douma <[email protected]>
7
 * @author Vincent Petry <[email protected]>
8
 *
9
 * @license AGPL-3.0
10
 *
11
 * This code is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License, version 3,
13
 * as published by the Free Software Foundation.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License, version 3,
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
22
 *
23
 */
24
namespace OCA\Files_Sharing\API;
25
26
use OCP\AppFramework\Http\DataResponse;
27
use OCP\AppFramework\OCS\OCSBadRequestException;
28
use OCP\AppFramework\OCS\OCSException;
29
use OCP\AppFramework\OCS\OCSForbiddenException;
30
use OCP\AppFramework\OCS\OCSNotFoundException;
31
use OCP\AppFramework\OCSController;
32
use OCP\Files\NotFoundException;
33
use OCP\IGroupManager;
34
use OCP\IL10N;
35
use OCP\IUserManager;
36
use OCP\IRequest;
37
use OCP\IURLGenerator;
38
use OCP\IUser;
39
use OCP\Files\IRootFolder;
40
use OCP\Lock\LockedException;
41
use OCP\Share\IManager;
42
use OCP\Share\Exceptions\ShareNotFound;
43
use OCP\Share\Exceptions\GenericShareException;
44
use OCP\Lock\ILockingProvider;
45
46
/**
47
 * Class Share20OCS
48
 *
49
 * @package OCA\Files_Sharing\API
50
 */
51
class Share20OCS extends OCSController {
52
53
	/** @var IManager */
54
	private $shareManager;
55
	/** @var IGroupManager */
56
	private $groupManager;
57
	/** @var IUserManager */
58
	private $userManager;
59
	/** @var IRequest */
60
	protected $request;
61
	/** @var IRootFolder */
62
	private $rootFolder;
63
	/** @var IURLGenerator */
64
	private $urlGenerator;
65
	/** @var IUser */
66
	private $currentUser;
67
	/** @var IL10N */
68
	private $l;
69
	/** @var \OCP\Files\Node */
70
	private $lockedNode;
71
72
	/**
73
	 * Share20OCS constructor.
74
	 *
75
	 * @param string $appName
76
	 * @param IRequest $request
77
	 * @param IManager $shareManager
78
	 * @param IGroupManager $groupManager
79
	 * @param IUserManager $userManager
80
	 * @param IRootFolder $rootFolder
81
	 * @param IURLGenerator $urlGenerator
82
	 * @param IUser $currentUser
83
	 * @param IL10N $l10n
84
	 */
85 View Code Duplication
	public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
86
			$appName,
87
			IRequest $request,
88
			IManager $shareManager,
89
			IGroupManager $groupManager,
90
			IUserManager $userManager,
91
			IRootFolder $rootFolder,
92
			IURLGenerator $urlGenerator,
93
			IUser $currentUser,
94
			IL10N $l10n
95
	) {
96
		parent::__construct($appName, $request);
97
98
		$this->shareManager = $shareManager;
99
		$this->userManager = $userManager;
100
		$this->groupManager = $groupManager;
101
		$this->request = $request;
102
		$this->rootFolder = $rootFolder;
103
		$this->urlGenerator = $urlGenerator;
104
		$this->currentUser = $currentUser;
105
		$this->l = $l10n;
106
	}
107
108
	/**
109
	 * Convert an IShare to an array for OCS output
110
	 *
111
	 * @param \OCP\Share\IShare $share
112
	 * @return array
113
	 * @throws NotFoundException In case the node can't be resolved.
114
	 */
115
	protected function formatShare(\OCP\Share\IShare $share) {
116
		$sharedBy = $this->userManager->get($share->getSharedBy());
117
		$shareOwner = $this->userManager->get($share->getShareOwner());
118
119
		$result = [
120
			'id' => $share->getId(),
121
			'share_type' => $share->getShareType(),
122
			'uid_owner' => $share->getSharedBy(),
123
			'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(),
124
			'permissions' => $share->getPermissions(),
125
			'stime' => $share->getShareTime()->getTimestamp(),
126
			'parent' => null,
127
			'expiration' => null,
128
			'token' => null,
129
			'uid_file_owner' => $share->getShareOwner(),
130
			'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(),
131
		];
132
133
		$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID());
134
		$nodes = $userFolder->getById($share->getNodeId());
135
136
		if (empty($nodes)) {
137
			throw new NotFoundException();
138
		}
139
140
		$node = $nodes[0];
141
142
		$result['path'] = $userFolder->getRelativePath($node->getPath());
143
		if ($node instanceOf \OCP\Files\Folder) {
144
			$result['item_type'] = 'folder';
145
		} else {
146
			$result['item_type'] = 'file';
147
		}
148
		$result['mimetype'] = $node->getMimetype();
149
		$result['storage_id'] = $node->getStorage()->getId();
150
		$result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
151
		$result['item_source'] = $node->getId();
152
		$result['file_source'] = $node->getId();
153
		$result['file_parent'] = $node->getParent()->getId();
154
		$result['file_target'] = $share->getTarget();
155
156
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
157
			$sharedWith = $this->userManager->get($share->getSharedWith());
158
			$result['share_with'] = $share->getSharedWith();
159
			$result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith();
160
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
161
			$result['share_with'] = $share->getSharedWith();
162
			$result['share_with_displayname'] = $share->getSharedWith();
163
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
164
165
			$result['share_with'] = $share->getPassword();
166
			$result['share_with_displayname'] = $share->getPassword();
167
168
			$result['token'] = $share->getToken();
169
			$result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
170
171
			$expiration = $share->getExpirationDate();
172
			if ($expiration !== null) {
173
				$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
174
			}
175
176
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
177
			$result['share_with'] = $share->getSharedWith();
178
			$result['share_with_displayname'] = $share->getSharedWith();
179
			$result['token'] = $share->getToken();
180
		}
181
182
		$result['mail_send'] = $share->getMailSend() ? 1 : 0;
183
184
		return $result;
185
	}
186
187
	/**
188
	 * Get a specific share by id
189
	 *
190
	 * @NoAdminRequired
191
	 *
192
	 * @param string $id
193
	 * @return DataResponse
194
	 * @throws OCSNotFoundException
195
	 */
196
	public function getShare($id) {
197
		try {
198
			$share = $this->getShareById($id);
199
		} catch (ShareNotFound $e) {
200
			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
201
		}
202
203
		if ($this->canAccessShare($share)) {
204
			try {
205
				$share = $this->formatShare($share);
206
				return new DataResponse(['data' => [$share]]);
207
			} catch (NotFoundException $e) {
208
				//Fall trough
209
			}
210
		}
211
212
		throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
213
	}
214
215
	/**
216
	 * Delete a share
217
	 *
218
	 * @NoAdminRequired
219
	 *
220
	 * @param string $id
221
	 * @return DataResponse
222
	 * @throws OCSNotFoundException
223
	 */
224
	public function deleteShare($id) {
225
		try {
226
			$share = $this->getShareById($id);
227
		} catch (ShareNotFound $e) {
228
			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
229
		}
230
231
		try {
232
			$this->lock($share->getNode());
233
		} catch (LockedException $e) {
234
			throw new OCSNotFoundException($this->l->t('could not delete share'));
235
		}
236
237
		if (!$this->canAccessShare($share, false)) {
238
			throw new OCSNotFoundException($this->l->t('Could not delete share'));
239
		}
240
241
		$this->shareManager->deleteShare($share);
242
243
		return new DataResponse();
244
	}
245
246
	/**
247
	 * @NoAdminRequired
248
	 *
249
	 * @return DataResponse
250
	 * @throws OCSNotFoundException
251
	 * @throws OCSForbiddenException
252
	 * @throws OCSBadRequestException
253
	 * @throws OCSException
254
	 */
255
	public function createShare() {
256
		$share = $this->shareManager->newShare();
257
258
		// Verify path
259
		$path = $this->request->getParam('path', null);
260
		if ($path === null) {
261
			throw new OCSNotFoundException($this->l->t('Please specify a file or folder path'));
262
		}
263
264
		$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID());
265
		try {
266
			$path = $userFolder->get($path);
267
		} catch (NotFoundException $e) {
268
			throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
269
		}
270
271
		$share->setNode($path);
272
273
		try {
274
			$this->lock($share->getNode());
275
		} catch (LockedException $e) {
276
			throw new OCSNotFoundException($this->l->t('Could not create share'));
277
		}
278
279
		// Parse permissions (if available)
280
		$permissions = $this->request->getParam('permissions', null);
281
		if ($permissions === null) {
282
			$permissions = \OCP\Constants::PERMISSION_ALL;
283
		} else {
284
			$permissions = (int)$permissions;
285
		}
286
287
		if ($permissions < 0 || $permissions > \OCP\Constants::PERMISSION_ALL) {
288
			throw new OCSNotFoundException($this->l->t('invalid permissions'));
289
		}
290
291
		// Shares always require read permissions
292
		$permissions |= \OCP\Constants::PERMISSION_READ;
293
294
		if ($path instanceof \OCP\Files\File) {
295
			// Single file shares should never have delete or create permissions
296
			$permissions &= ~\OCP\Constants::PERMISSION_DELETE;
297
			$permissions &= ~\OCP\Constants::PERMISSION_CREATE;
298
		}
299
300
		/*
301
		 * Hack for https://github.com/owncloud/core/issues/22587
302
		 * We check the permissions via webdav. But the permissions of the mount point
303
		 * do not equal the share permissions. Here we fix that for federated mounts.
304
		 */
305
		if ($path->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
306
			$permissions &= ~($permissions & ~$path->getPermissions());
307
		}
308
309
		$shareWith = $this->request->getParam('shareWith', null);
310
		$shareType = (int)$this->request->getParam('shareType', '-1');
311
312
		if ($shareType === \OCP\Share::SHARE_TYPE_USER) {
313
			// Valid user is required to share
314
			if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
315
				throw new OCSNotFoundException($this->l->t('Please specify a valid user'));
316
			}
317
			$share->setSharedWith($shareWith);
318
			$share->setPermissions($permissions);
319
		} else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
320
			if (!$this->shareManager->allowGroupSharing()) {
321
				throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator'));
322
			}
323
324
			// Valid group is required to share
325
			if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
326
				throw new OCSNotFoundException($this->l->t('Please specify a valid group'));
327
			}
328
			$share->setSharedWith($shareWith);
329
			$share->setPermissions($permissions);
330
		} else if ($shareType === \OCP\Share::SHARE_TYPE_LINK) {
331
			//Can we even share links?
332
			if (!$this->shareManager->shareApiAllowLinks()) {
333
				throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator'));
334
			}
335
336
			/*
337
			 * For now we only allow 1 link share.
338
			 * Return the existing link share if this is a duplicate
339
			 */
340
			$existingShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, false, 1, 0);
341
			if (!empty($existingShares)) {
342
				return new DataResponse(['data' => $this->formatShare($existingShares[0])]);
343
			}
344
345
			$publicUpload = $this->request->getParam('publicUpload', null);
346
			if ($publicUpload === 'true') {
347
				// Check if public upload is allowed
348
				if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
349
					throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
350
				}
351
352
				// Public upload can only be set for folders
353
				if ($path instanceof \OCP\Files\File) {
354
					throw new OCSNotFoundException($this->l->t('Public upload is only possible for publicly shared folders'));
355
				}
356
357
				$share->setPermissions(
358
					\OCP\Constants::PERMISSION_READ |
359
					\OCP\Constants::PERMISSION_CREATE |
360
					\OCP\Constants::PERMISSION_UPDATE |
361
					\OCP\Constants::PERMISSION_DELETE
362
				);
363
			} else {
364
				$share->setPermissions(\OCP\Constants::PERMISSION_READ);
365
			}
366
367
			// Set password
368
			$password = $this->request->getParam('password', '');
369
370
			if ($password !== '') {
371
				$share->setPassword($password);
372
			}
373
374
			//Expire date
375
			$expireDate = $this->request->getParam('expireDate', '');
376
377
			if ($expireDate !== '') {
378
				try {
379
					$expireDate = $this->parseDate($expireDate);
380
					$share->setExpirationDate($expireDate);
381
				} catch (\Exception $e) {
382
					throw new OCSNotFoundException($this->l->t('Invalid date, date format must be YYYY-MM-DD'));
383
				}
384
			}
385
386
		} else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
387
			if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
388
				throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType]));
389
			}
390
391
			$share->setSharedWith($shareWith);
392
			$share->setPermissions($permissions);
393
		} else {
394
			throw new OCSBadRequestException($this->l->t('Unknown share type'));
395
		}
396
397
		$share->setShareType($shareType);
398
		$share->setSharedBy($this->currentUser->getUID());
399
400
		try {
401
			$share = $this->shareManager->createShare($share);
402
		} catch (GenericShareException $e) {
403
			$code = $e->getCode() === 0 ? 403 : $e->getCode();
404
			throw new OCSException($e->getHint(), $code);
405
		}catch (\Exception $e) {
406
			throw new OCSForbiddenException($e->getMessage());
407
		}
408
409
		$output = $this->formatShare($share);
410
411
		return new DataResponse(['data' => $output]);
412
	}
413
414
	/**
415
	 * @param \OCP\Files\File|\OCP\Files\Folder $node
416
	 * @return DataResponse
417
	 */
418
	private function getSharedWithMe($node = null) {
419
		$userShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, -1, 0);
420
		$groupShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0);
421
422
		$shares = array_merge($userShares, $groupShares);
423
424
		$formatted = [];
425
		foreach ($shares as $share) {
426
			if ($this->canAccessShare($share)) {
427
				try {
428
					$formatted[] = $this->formatShare($share);
429
				} catch (NotFoundException $e) {
430
					// Ignore this share
431
				}
432
			}
433
		}
434
435
		return new DataResponse(['data' => $formatted]);
436
	}
437
438
	/**
439
	 * @param \OCP\Files\Folder $folder
440
	 * @return DataResponse
441
	 * @throws OCSBadRequestException
442
	 */
443
	private function getSharesInDir($folder) {
444
		if (!($folder instanceof \OCP\Files\Folder)) {
445
			throw new OCSBadRequestException($this->l->t('Not a directory'));
446
		}
447
448
		$nodes = $folder->getDirectoryListing();
449
		/** @var \OCP\Share\IShare[] $shares */
450
		$shares = [];
451
		foreach ($nodes as $node) {
452
			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, false, -1, 0));
453
			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, false, -1, 0));
454
			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $node, false, -1, 0));
455
			if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
456
				$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_REMOTE, $node, false, -1, 0));
457
			}
458
		}
459
460
		$formatted = [];
461
		foreach ($shares as $share) {
462
			try {
463
				$formatted[] = $this->formatShare($share);
464
			} catch (NotFoundException $e) {
465
				//Ignore this share
466
			}
467
		}
468
469
		return new DataResponse(['data' => $formatted]);
470
	}
471
472
	/**
473
	 * The getShares function.
474
	 *
475
	 * @NoAdminRequired
476
	 *
477
	 * - Get shares by the current user
478
	 * - Get shares by the current user and reshares (?reshares=true)
479
	 * - Get shares with the current user (?shared_with_me=true)
480
	 * - Get shares for a specific path (?path=...)
481
	 * - Get all shares in a folder (?subfiles=true&path=..)
482
	 *
483
	 * @return DataResponse
484
	 * @throws OCSNotFoundException
485
	 */
486
	public function getShares() {
487
		$sharedWithMe = $this->request->getParam('shared_with_me', null);
488
		$reshares = $this->request->getParam('reshares', null);
489
		$subfiles = $this->request->getParam('subfiles');
490
		$path = $this->request->getParam('path', null);
491
492
		if ($path !== null) {
493
			$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID());
494
			try {
495
				$path = $userFolder->get($path);
496
				$this->lock($path);
497
			} catch (\OCP\Files\NotFoundException $e) {
498
				throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
499
			} catch (LockedException $e) {
500
				throw new OCSNotFoundException($this->l->t('Could not lock path'));
501
			}
502
		}
503
504
		if ($sharedWithMe === 'true') {
505
			$result = $this->getSharedWithMe($path);
0 ignored issues
show
Bug introduced by
It seems like $path can also be of type object<OCP\Files\Node>; however, OCA\Files_Sharing\API\Sh...0OCS::getSharedWithMe() does only seem to accept object<OCP\Files\File>|o...<OCP\Files\Folder>|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
506
			return $result;
507
		}
508
509
		if ($subfiles === 'true') {
510
			$result = $this->getSharesInDir($path);
0 ignored issues
show
Documentation introduced by
$path is of type object<OCP\Files\Node>|null, but the function expects a object<OCP\Files\Folder>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
511
			return $result;
512
		}
513
514
		if ($reshares === 'true') {
515
			$reshares = true;
516
		} else {
517
			$reshares = false;
518
		}
519
520
		// Get all shares
521
		$userShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
522
		$groupShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
523
		$linkShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
524
		$shares = array_merge($userShares, $groupShares, $linkShares);
525
526
		if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
527
			$federatedShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
528
			$shares = array_merge($shares, $federatedShares);
529
		}
530
531
		$formatted = [];
532
		foreach ($shares as $share) {
533
			try {
534
				$formatted[] = $this->formatShare($share);
535
			} catch (NotFoundException $e) {
536
				//Ignore share
537
			}
538
		}
539
540
		return new DataResponse(['data' => $formatted]);
541
	}
542
543
	/**
544
	 * @NoAdminRequired
545
	 *
546
	 * @param int $id
547
	 * @return DataResponse
548
	 * @throws OCSNotFoundException
549
	 * @throws OCSBadRequestException
550
	 * @throws OCSForbiddenException
551
	 */
552
	public function updateShare($id) {
553
		try {
554
			$share = $this->getShareById($id);
555
		} catch (ShareNotFound $e) {
556
			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
557
		}
558
559
		$this->lock($share->getNode());
560
561
		if (!$this->canAccessShare($share, false)) {
562
			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
563
		}
564
565
		$permissions = $this->request->getParam('permissions', null);
566
		$password = $this->request->getParam('password', null);
567
		$publicUpload = $this->request->getParam('publicUpload', null);
568
		$expireDate = $this->request->getParam('expireDate', null);
569
570
		/*
571
		 * expirationdate, password and publicUpload only make sense for link shares
572
		 */
573
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
574
			if ($permissions === null && $password === null && $publicUpload === null && $expireDate === null) {
575
				throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
576
			}
577
578
			$newPermissions = null;
579
			if ($publicUpload === 'true') {
580
				$newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE;
581
			} else if ($publicUpload === 'false') {
582
				$newPermissions = \OCP\Constants::PERMISSION_READ;
583
			}
584
585
			if ($permissions !== null) {
586
				$newPermissions = (int)$permissions;
587
			}
588
589
			if ($newPermissions !== null &&
590
				!in_array($newPermissions, [
591
					\OCP\Constants::PERMISSION_READ,
592
					\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE, // legacy
593
					\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE, // correct
594
					\OCP\Constants::PERMISSION_CREATE, // hidden file list
595
				])
596
			) {
597
				throw new OCSBadRequestException($this->l->t('Can\'t change permissions for public share links'));
598
			}
599
600
			if (
601
				// legacy
602
				$newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) ||
603
				// correct
604
				$newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE)
605
			) {
606
				if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
607
					throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
608
				}
609
610
				if (!($share->getNode() instanceof \OCP\Files\Folder)) {
611
					throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders'));
612
				}
613
614
				// normalize to correct public upload permissions
615
				$newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE;
616
			}
617
618
			if ($newPermissions !== null) {
619
				$share->setPermissions($newPermissions);
620
			}
621
622
			if ($expireDate === '') {
623
				$share->setExpirationDate(null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a object<DateTime>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
624
			} else if ($expireDate !== null) {
625
				try {
626
					$expireDate = $this->parseDate($expireDate);
627
				} catch (\Exception $e) {
628
					throw new OCSBadRequestException($e->getMessage());
629
				}
630
				$share->setExpirationDate($expireDate);
631
			}
632
633
			if ($password === '') {
634
				$share->setPassword(null);
635
			} else if ($password !== null) {
636
				$share->setPassword($password);
637
			}
638
639
		} else {
640
			// For other shares only permissions is valid.
641
			if ($permissions === null) {
642
				throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
643
			} else {
644
				$permissions = (int)$permissions;
645
				$share->setPermissions($permissions);
646
			}
647
		}
648
649
		if ($permissions !== null) {
650
			/* Check if this is an incomming share */
651
			$incomingShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0);
652
			$incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0));
653
654
			/** @var \OCP\Share\IShare[] $incomingShares */
655
			if (!empty($incomingShares)) {
656
				$maxPermissions = 0;
657
				foreach ($incomingShares as $incomingShare) {
658
					$maxPermissions |= $incomingShare->getPermissions();
659
				}
660
661
				if ($share->getPermissions() & ~$maxPermissions) {
662
					throw new OCSNotFoundException($this->l->t('Cannot increase permissions'));
663
				}
664
			}
665
		}
666
667
668
		try {
669
			$share = $this->shareManager->updateShare($share);
670
		} catch (\Exception $e) {
671
			throw new OCSBadRequestException($e->getMessage());
672
		}
673
674
		return new DataResponse(['data' => $this->formatShare($share)]);
675
	}
676
677
	/**
678
	 * @param \OCP\Share\IShare $share
679
	 * @return bool
680
	 */
681
	protected function canAccessShare(\OCP\Share\IShare $share, $checkGroups = true) {
682
		// A file with permissions 0 can't be accessed by us. So Don't show it
683
		if ($share->getPermissions() === 0) {
684
			return false;
685
		}
686
687
		// Owner of the file and the sharer of the file can always get share
688
		if ($share->getShareOwner() === $this->currentUser->getUID() ||
689
			$share->getSharedBy() === $this->currentUser->getUID()
690
		) {
691
			return true;
692
		}
693
694
		// If the share is shared with you (or a group you are a member of)
695
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
696
			$share->getSharedWith() === $this->currentUser->getUID()) {
697
			return true;
698
		}
699
700
		if ($checkGroups && $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
701
			$sharedWith = $this->groupManager->get($share->getSharedWith());
702
			if ($sharedWith->inGroup($this->currentUser)) {
703
				return true;
704
			}
705
		}
706
707
		return false;
708
	}
709
710
	/**
711
	 * Make sure that the passed date is valid ISO 8601
712
	 * So YYYY-MM-DD
713
	 * If not throw an exception
714
	 *
715
	 * @param string $expireDate
716
	 *
717
	 * @throws \Exception
718
	 * @return \DateTime
719
	 */
720
	private function parseDate($expireDate) {
721
		try {
722
			$date = new \DateTime($expireDate);
723
		} catch (\Exception $e) {
724
			throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
725
		}
726
727
		if ($date === false) {
728
			throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
729
		}
730
731
		$date->setTime(0,0,0);
732
733
		return $date;
734
	}
735
736
	/**
737
	 * Since we have multiple providers but the OCS Share API v1 does
738
	 * not support this we need to check all backends.
739
	 *
740
	 * @param string $id
741
	 * @return \OCP\Share\IShare
742
	 * @throws ShareNotFound
743
	 */
744
	private function getShareById($id) {
745
		$share = null;
746
747
		// First check if it is an internal share.
748
		try {
749
			$share = $this->shareManager->getShareById('ocinternal:'.$id);
750
		} catch (ShareNotFound $e) {
751
			if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
752
				throw new ShareNotFound();
753
			}
754
755
			$share = $this->shareManager->getShareById('ocFederatedSharing:' . $id);
756
		}
757
758
		return $share;
759
	}
760
761
	/**
762
	 * Lock a Node
763
	 * @param \OCP\Files\Node $node
764
	 */
765
	private function lock(\OCP\Files\Node $node) {
766
		$node->lock(ILockingProvider::LOCK_SHARED);
767
		$this->lockedNode = $node;
768
	}
769
770
	/**
771
	 * Cleanup the remaining locks
772
	 */
773
	public function cleanup() {
774
		if ($this->lockedNode !== null) {
775
			$this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
776
		}
777
	}
778
}
779