Completed
Push — master ( 0a33eb...25a1a6 )
by Lukas
08:58
created

Share20OCS::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 19
nc 1
nop 9
dl 0
loc 22
rs 9.2
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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
use OCP\Share\IShare;
46
47
/**
48
 * Class Share20OCS
49
 *
50
 * @package OCA\Files_Sharing\API
51
 */
52
class Share20OCS extends OCSController {
53
54
	/** @var IManager */
55
	private $shareManager;
56
	/** @var IGroupManager */
57
	private $groupManager;
58
	/** @var IUserManager */
59
	private $userManager;
60
	/** @var IRequest */
61
	protected $request;
62
	/** @var IRootFolder */
63
	private $rootFolder;
64
	/** @var IURLGenerator */
65
	private $urlGenerator;
66
	/** @var IUser */
67
	private $currentUser;
68
	/** @var IL10N */
69
	private $l;
70
	/** @var \OCP\Files\Node */
71
	private $lockedNode;
72
73
	/**
74
	 * Share20OCS constructor.
75
	 *
76
	 * @param string $appName
77
	 * @param IRequest $request
78
	 * @param IManager $shareManager
79
	 * @param IGroupManager $groupManager
80
	 * @param IUserManager $userManager
81
	 * @param IRootFolder $rootFolder
82
	 * @param IURLGenerator $urlGenerator
83
	 * @param IUser $currentUser
84
	 * @param IL10N $l10n
85
	 */
86
	public function __construct(
87
			$appName,
88
			IRequest $request,
89
			IManager $shareManager,
90
			IGroupManager $groupManager,
91
			IUserManager $userManager,
92
			IRootFolder $rootFolder,
93
			IURLGenerator $urlGenerator,
94
			IUser $currentUser,
95
			IL10N $l10n
96
	) {
97
		parent::__construct($appName, $request);
98
99
		$this->shareManager = $shareManager;
100
		$this->userManager = $userManager;
101
		$this->groupManager = $groupManager;
102
		$this->request = $request;
103
		$this->rootFolder = $rootFolder;
104
		$this->urlGenerator = $urlGenerator;
105
		$this->currentUser = $currentUser;
106
		$this->l = $l10n;
107
	}
108
109
	/**
110
	 * Convert an IShare to an array for OCS output
111
	 *
112
	 * @param \OCP\Share\IShare $share
113
	 * @return array
114
	 * @throws NotFoundException In case the node can't be resolved.
115
	 */
116
	protected function formatShare(\OCP\Share\IShare $share) {
117
		$sharedBy = $this->userManager->get($share->getSharedBy());
118
		$shareOwner = $this->userManager->get($share->getShareOwner());
119
120
		$result = [
121
			'id' => $share->getId(),
122
			'share_type' => $share->getShareType(),
123
			'uid_owner' => $share->getSharedBy(),
124
			'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(),
125
			'permissions' => $share->getPermissions(),
126
			'stime' => $share->getShareTime()->getTimestamp(),
127
			'parent' => null,
128
			'expiration' => null,
129
			'token' => null,
130
			'uid_file_owner' => $share->getShareOwner(),
131
			'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(),
132
		];
133
134
		$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID());
135
		$nodes = $userFolder->getById($share->getNodeId());
136
137
		if (empty($nodes)) {
138
			throw new NotFoundException();
139
		}
140
141
		$node = $nodes[0];
142
143
		$result['path'] = $userFolder->getRelativePath($node->getPath());
144
		if ($node instanceOf \OCP\Files\Folder) {
145
			$result['item_type'] = 'folder';
146
		} else {
147
			$result['item_type'] = 'file';
148
		}
149
		$result['mimetype'] = $node->getMimetype();
150
		$result['storage_id'] = $node->getStorage()->getId();
151
		$result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
152
		$result['item_source'] = $node->getId();
153
		$result['file_source'] = $node->getId();
154
		$result['file_parent'] = $node->getParent()->getId();
155
		$result['file_target'] = $share->getTarget();
156
157
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
158
			$sharedWith = $this->userManager->get($share->getSharedWith());
159
			$result['share_with'] = $share->getSharedWith();
160
			$result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith();
161
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
162
			$result['share_with'] = $share->getSharedWith();
163
			$result['share_with_displayname'] = $share->getSharedWith();
164
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
165
166
			$result['share_with'] = $share->getPassword();
167
			$result['share_with_displayname'] = $share->getPassword();
168
169
			$result['token'] = $share->getToken();
170
			$result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
171
172
			$expiration = $share->getExpirationDate();
173
			if ($expiration !== null) {
174
				$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
175
			}
176
177
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
178
			$result['share_with'] = $share->getSharedWith();
179
			$result['share_with_displayname'] = $share->getSharedWith();
180
			$result['token'] = $share->getToken();
181
		}
182
183
		$result['mail_send'] = $share->getMailSend() ? 1 : 0;
184
185
		return $result;
186
	}
187
188
	/**
189
	 * Get a specific share by id
190
	 *
191
	 * @NoAdminRequired
192
	 *
193
	 * @param string $id
194
	 * @return DataResponse
195
	 * @throws OCSNotFoundException
196
	 */
197
	public function getShare($id) {
198
		try {
199
			$share = $this->getShareById($id);
200
		} catch (ShareNotFound $e) {
201
			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
202
		}
203
204
		if ($this->canAccessShare($share)) {
205
			try {
206
				$share = $this->formatShare($share);
207
				return new DataResponse([$share]);
208
			} catch (NotFoundException $e) {
209
				//Fall trough
210
			}
211
		}
212
213
		throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
214
	}
215
216
	/**
217
	 * Delete a share
218
	 *
219
	 * @NoAdminRequired
220
	 *
221
	 * @param string $id
222
	 * @return DataResponse
223
	 * @throws OCSNotFoundException
224
	 */
225
	public function deleteShare($id) {
226
		try {
227
			$share = $this->getShareById($id);
228
		} catch (ShareNotFound $e) {
229
			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
230
		}
231
232
		try {
233
			$this->lock($share->getNode());
234
		} catch (LockedException $e) {
235
			throw new OCSNotFoundException($this->l->t('could not delete share'));
236
		}
237
238
		if (!$this->canAccessShare($share, false)) {
239
			throw new OCSNotFoundException($this->l->t('Could not delete share'));
240
		}
241
242
		$this->shareManager->deleteShare($share);
243
244
		return new DataResponse();
245
	}
246
247
	/**
248
	 * @NoAdminRequired
249
	 *
250
	 * @param string $path
251
	 * @param int $permissions
252
	 * @param int $shareType
253
	 * @param string $shareWith
254
	 * @param string $publicUpload
255
	 * @param string $password
256
	 * @param string $expireDate
257
	 *
258
	 * @return DataResponse
259
	 * @throws OCSNotFoundException
260
	 * @throws OCSForbiddenException
261
	 * @throws OCSBadRequestException
262
	 * @throws OCSException
263
	 */
264
	public function createShare(
265
		$path = null,
266
		$permissions = \OCP\Constants::PERMISSION_ALL,
267
		$shareType = -1,
268
		$shareWith = null,
269
		$publicUpload = 'false',
270
		$password = '',
271
		$expireDate = ''
272
	) {
273
		$share = $this->shareManager->newShare();
274
275
		// Verify path
276
		if ($path === null) {
277
			throw new OCSNotFoundException($this->l->t('Please specify a file or folder path'));
278
		}
279
280
		$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID());
281
		try {
282
			$path = $userFolder->get($path);
283
		} catch (NotFoundException $e) {
284
			throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
285
		}
286
287
		$share->setNode($path);
288
289
		try {
290
			$this->lock($share->getNode());
291
		} catch (LockedException $e) {
292
			throw new OCSNotFoundException($this->l->t('Could not create share'));
293
		}
294
295
		if ($permissions < 0 || $permissions > \OCP\Constants::PERMISSION_ALL) {
296
			throw new OCSNotFoundException($this->l->t('invalid permissions'));
297
		}
298
299
		// Shares always require read permissions
300
		$permissions |= \OCP\Constants::PERMISSION_READ;
301
302
		if ($path instanceof \OCP\Files\File) {
303
			// Single file shares should never have delete or create permissions
304
			$permissions &= ~\OCP\Constants::PERMISSION_DELETE;
305
			$permissions &= ~\OCP\Constants::PERMISSION_CREATE;
306
		}
307
308
		/*
309
		 * Hack for https://github.com/owncloud/core/issues/22587
310
		 * We check the permissions via webdav. But the permissions of the mount point
311
		 * do not equal the share permissions. Here we fix that for federated mounts.
312
		 */
313
		if ($path->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
314
			$permissions &= ~($permissions & ~$path->getPermissions());
315
		}
316
317
		if ($shareType === \OCP\Share::SHARE_TYPE_USER) {
318
			// Valid user is required to share
319
			if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
320
				throw new OCSNotFoundException($this->l->t('Please specify a valid user'));
321
			}
322
			$share->setSharedWith($shareWith);
323
			$share->setPermissions($permissions);
324
		} else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) {
325
			if (!$this->shareManager->allowGroupSharing()) {
326
				throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator'));
327
			}
328
329
			// Valid group is required to share
330
			if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
331
				throw new OCSNotFoundException($this->l->t('Please specify a valid group'));
332
			}
333
			$share->setSharedWith($shareWith);
334
			$share->setPermissions($permissions);
335
		} else if ($shareType === \OCP\Share::SHARE_TYPE_LINK) {
336
			//Can we even share links?
337
			if (!$this->shareManager->shareApiAllowLinks()) {
338
				throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator'));
339
			}
340
341
			/*
342
			 * For now we only allow 1 link share.
343
			 * Return the existing link share if this is a duplicate
344
			 */
345
			$existingShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, false, 1, 0);
346
			if (!empty($existingShares)) {
347
				return new DataResponse($this->formatShare($existingShares[0]));
348
			}
349
350
			if ($publicUpload === 'true') {
351
				// Check if public upload is allowed
352
				if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
353
					throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
354
				}
355
356
				// Public upload can only be set for folders
357
				if ($path instanceof \OCP\Files\File) {
358
					throw new OCSNotFoundException($this->l->t('Public upload is only possible for publicly shared folders'));
359
				}
360
361
				$share->setPermissions(
362
					\OCP\Constants::PERMISSION_READ |
363
					\OCP\Constants::PERMISSION_CREATE |
364
					\OCP\Constants::PERMISSION_UPDATE |
365
					\OCP\Constants::PERMISSION_DELETE
366
				);
367
			} else {
368
				$share->setPermissions(\OCP\Constants::PERMISSION_READ);
369
			}
370
371
			// Set password
372
			if ($password !== '') {
373
				$share->setPassword($password);
374
			}
375
376
			//Expire date
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($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
		$shares = array_filter($shares, function(IShare $share) {
425
			return $share->getShareOwner() !== $this->currentUser->getUID();
426
		});
427
428
		$formatted = [];
429
		foreach ($shares as $share) {
430
			if ($this->canAccessShare($share)) {
431
				try {
432
					$formatted[] = $this->formatShare($share);
433
				} catch (NotFoundException $e) {
434
					// Ignore this share
435
				}
436
			}
437
		}
438
439
		return new DataResponse($formatted);
440
	}
441
442
	/**
443
	 * @param \OCP\Files\Folder $folder
444
	 * @return DataResponse
445
	 * @throws OCSBadRequestException
446
	 */
447
	private function getSharesInDir($folder) {
448
		if (!($folder instanceof \OCP\Files\Folder)) {
449
			throw new OCSBadRequestException($this->l->t('Not a directory'));
450
		}
451
452
		$nodes = $folder->getDirectoryListing();
453
		/** @var \OCP\Share\IShare[] $shares */
454
		$shares = [];
455
		foreach ($nodes as $node) {
456
			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, false, -1, 0));
457
			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, false, -1, 0));
458
			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $node, false, -1, 0));
459
			if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
460
				$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_REMOTE, $node, false, -1, 0));
461
			}
462
		}
463
464
		$formatted = [];
465
		foreach ($shares as $share) {
466
			try {
467
				$formatted[] = $this->formatShare($share);
468
			} catch (NotFoundException $e) {
469
				//Ignore this share
470
			}
471
		}
472
473
		return new DataResponse($formatted);
474
	}
475
476
	/**
477
	 * The getShares function.
478
	 *
479
	 * @NoAdminRequired
480
	 *
481
	 * @param string $shared_with_me
482
	 * @param string $reshares
483
	 * @param string $subfiles
484
	 * @param string $path
485
	 *
486
	 * - Get shares by the current user
487
	 * - Get shares by the current user and reshares (?reshares=true)
488
	 * - Get shares with the current user (?shared_with_me=true)
489
	 * - Get shares for a specific path (?path=...)
490
	 * - Get all shares in a folder (?subfiles=true&path=..)
491
	 *
492
	 * @return DataResponse
493
	 * @throws OCSNotFoundException
494
	 */
495
	public function getShares(
496
		$shared_with_me = 'false',
497
		$reshares = 'false',
498
		$subfiles = 'false',
499
		$path = null
500
	) {
501
502
		if ($path !== null) {
503
			$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID());
504
			try {
505
				$path = $userFolder->get($path);
506
				$this->lock($path);
507
			} catch (\OCP\Files\NotFoundException $e) {
508
				throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
509
			} catch (LockedException $e) {
510
				throw new OCSNotFoundException($this->l->t('Could not lock path'));
511
			}
512
		}
513
514
		if ($shared_with_me === 'true') {
515
			$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...
516
			return $result;
517
		}
518
519
		if ($subfiles === 'true') {
520
			$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...
521
			return $result;
522
		}
523
524
		if ($reshares === 'true') {
525
			$reshares = true;
526
		} else {
527
			$reshares = false;
528
		}
529
530
		// Get all shares
531
		$userShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
532
		$groupShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
533
		$linkShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
534
		$shares = array_merge($userShares, $groupShares, $linkShares);
535
536
		if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
537
			$federatedShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
538
			$shares = array_merge($shares, $federatedShares);
539
		}
540
541
		$formatted = [];
542
		foreach ($shares as $share) {
543
			try {
544
				$formatted[] = $this->formatShare($share);
545
			} catch (NotFoundException $e) {
546
				//Ignore share
547
			}
548
		}
549
550
		return new DataResponse($formatted);
551
	}
552
553
	/**
554
	 * @NoAdminRequired
555
	 *
556
	 * @param int $id
557
	 * @param int $permissions
558
	 * @param string $password
559
	 * @param string $publicUpload
560
	 * @param string $expireDate
561
	 * @return DataResponse
562
	 * @throws OCSNotFoundException
563
	 * @throws OCSBadRequestException
564
	 * @throws OCSForbiddenException
565
	 */
566
	public function updateShare(
567
		$id,
568
		$permissions = null,
569
		$password = null,
570
		$publicUpload = null,
571
		$expireDate = null
572
	) {
573
		try {
574
			$share = $this->getShareById($id);
575
		} catch (ShareNotFound $e) {
576
			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
577
		}
578
579
		$this->lock($share->getNode());
580
581
		if (!$this->canAccessShare($share, false)) {
582
			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
583
		}
584
585
		/*
586
		 * expirationdate, password and publicUpload only make sense for link shares
587
		 */
588
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
589
			if ($permissions === null && $password === null && $publicUpload === null && $expireDate === null) {
590
				throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
591
			}
592
593
			$newPermissions = null;
594
			if ($publicUpload === 'true') {
595
				$newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE;
596
			} else if ($publicUpload === 'false') {
597
				$newPermissions = \OCP\Constants::PERMISSION_READ;
598
			}
599
600
			if ($permissions !== null) {
601
				$newPermissions = (int)$permissions;
602
			}
603
604
			if ($newPermissions !== null &&
605
				!in_array($newPermissions, [
606
					\OCP\Constants::PERMISSION_READ,
607
					\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE, // legacy
608
					\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE, // correct
609
					\OCP\Constants::PERMISSION_CREATE, // hidden file list
610
				])
611
			) {
612
				throw new OCSBadRequestException($this->l->t('Can\'t change permissions for public share links'));
613
			}
614
615
			if (
616
				// legacy
617
				$newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) ||
618
				// correct
619
				$newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE)
620
			) {
621
				if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
622
					throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
623
				}
624
625
				if (!($share->getNode() instanceof \OCP\Files\Folder)) {
626
					throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders'));
627
				}
628
629
				// normalize to correct public upload permissions
630
				$newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE;
631
			}
632
633
			if ($newPermissions !== null) {
634
				$share->setPermissions($newPermissions);
635
			}
636
637
			if ($expireDate === '') {
638
				$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...
639
			} else if ($expireDate !== null) {
640
				try {
641
					$expireDate = $this->parseDate($expireDate);
642
				} catch (\Exception $e) {
643
					throw new OCSBadRequestException($e->getMessage());
644
				}
645
				$share->setExpirationDate($expireDate);
646
			}
647
648
			if ($password === '') {
649
				$share->setPassword(null);
650
			} else if ($password !== null) {
651
				$share->setPassword($password);
652
			}
653
654
		} else {
655
			// For other shares only permissions is valid.
656
			if ($permissions === null) {
657
				throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
658
			} else {
659
				$permissions = (int)$permissions;
660
				$share->setPermissions($permissions);
661
			}
662
		}
663
664
		if ($permissions !== null) {
665
			/* Check if this is an incomming share */
666
			$incomingShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0);
667
			$incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0));
668
669
			/** @var \OCP\Share\IShare[] $incomingShares */
670
			if (!empty($incomingShares)) {
671
				$maxPermissions = 0;
672
				foreach ($incomingShares as $incomingShare) {
673
					$maxPermissions |= $incomingShare->getPermissions();
674
				}
675
676
				if ($share->getPermissions() & ~$maxPermissions) {
677
					throw new OCSNotFoundException($this->l->t('Cannot increase permissions'));
678
				}
679
			}
680
		}
681
682
683
		try {
684
			$share = $this->shareManager->updateShare($share);
685
		} catch (\Exception $e) {
686
			throw new OCSBadRequestException($e->getMessage());
687
		}
688
689
		return new DataResponse($this->formatShare($share));
690
	}
691
692
	/**
693
	 * @param \OCP\Share\IShare $share
694
	 * @return bool
695
	 */
696
	protected function canAccessShare(\OCP\Share\IShare $share, $checkGroups = true) {
697
		// A file with permissions 0 can't be accessed by us. So Don't show it
698
		if ($share->getPermissions() === 0) {
699
			return false;
700
		}
701
702
		// Owner of the file and the sharer of the file can always get share
703
		if ($share->getShareOwner() === $this->currentUser->getUID() ||
704
			$share->getSharedBy() === $this->currentUser->getUID()
705
		) {
706
			return true;
707
		}
708
709
		// If the share is shared with you (or a group you are a member of)
710
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
711
			$share->getSharedWith() === $this->currentUser->getUID()) {
712
			return true;
713
		}
714
715
		if ($checkGroups && $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
716
			$sharedWith = $this->groupManager->get($share->getSharedWith());
717
			if ($sharedWith->inGroup($this->currentUser)) {
718
				return true;
719
			}
720
		}
721
722
		return false;
723
	}
724
725
	/**
726
	 * Make sure that the passed date is valid ISO 8601
727
	 * So YYYY-MM-DD
728
	 * If not throw an exception
729
	 *
730
	 * @param string $expireDate
731
	 *
732
	 * @throws \Exception
733
	 * @return \DateTime
734
	 */
735
	private function parseDate($expireDate) {
736
		try {
737
			$date = new \DateTime($expireDate);
738
		} catch (\Exception $e) {
739
			throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
740
		}
741
742
		if ($date === false) {
743
			throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
744
		}
745
746
		$date->setTime(0,0,0);
747
748
		return $date;
749
	}
750
751
	/**
752
	 * Since we have multiple providers but the OCS Share API v1 does
753
	 * not support this we need to check all backends.
754
	 *
755
	 * @param string $id
756
	 * @return \OCP\Share\IShare
757
	 * @throws ShareNotFound
758
	 */
759
	private function getShareById($id) {
760
		$share = null;
761
762
		// First check if it is an internal share.
763
		try {
764
			$share = $this->shareManager->getShareById('ocinternal:'.$id);
765
		} catch (ShareNotFound $e) {
766
			if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
767
				throw new ShareNotFound();
768
			}
769
770
			$share = $this->shareManager->getShareById('ocFederatedSharing:' . $id);
771
		}
772
773
		return $share;
774
	}
775
776
	/**
777
	 * Lock a Node
778
	 * @param \OCP\Files\Node $node
779
	 */
780
	private function lock(\OCP\Files\Node $node) {
781
		$node->lock(ILockingProvider::LOCK_SHARED);
782
		$this->lockedNode = $node;
783
	}
784
785
	/**
786
	 * Cleanup the remaining locks
787
	 */
788
	public function cleanup() {
789
		if ($this->lockedNode !== null) {
790
			$this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
791
		}
792
	}
793
}
794