Passed
Push — master ( ccc0a5...5195be )
by Roeland
10:43 queued 11s
created

Manager::groupDeleted()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Bjoern Schiessle <[email protected]>
7
 * @author Björn Schießle <[email protected]>
8
 * @author Daniel Calviño Sánchez <[email protected]>
9
 * @author Jan-Christoph Borchardt <[email protected]>
10
 * @author Joas Schilling <[email protected]>
11
 * @author Julius Härtl <[email protected]>
12
 * @author Lukas Reschke <[email protected]>
13
 * @author Maxence Lange <[email protected]>
14
 * @author Maxence Lange <[email protected]>
15
 * @author Morris Jobke <[email protected]>
16
 * @author Pauli Järvinen <[email protected]>
17
 * @author Robin Appelman <[email protected]>
18
 * @author Roeland Jago Douma <[email protected]>
19
 * @author Stephan Müller <[email protected]>
20
 * @author Vincent Petry <[email protected]>
21
 *
22
 * @license AGPL-3.0
23
 *
24
 * This code is free software: you can redistribute it and/or modify
25
 * it under the terms of the GNU Affero General Public License, version 3,
26
 * as published by the Free Software Foundation.
27
 *
28
 * This program is distributed in the hope that it will be useful,
29
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31
 * GNU Affero General Public License for more details.
32
 *
33
 * You should have received a copy of the GNU Affero General Public License, version 3,
34
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
35
 *
36
 */
37
38
namespace OC\Share20;
39
40
use OC\Cache\CappedMemoryCache;
41
use OC\Files\Mount\MoveableMount;
42
use OC\HintException;
43
use OC\Share20\Exception\ProviderException;
44
use OCP\Files\File;
45
use OCP\Files\Folder;
46
use OCP\Files\IRootFolder;
47
use OCP\Files\Mount\IMountManager;
48
use OCP\Files\Node;
49
use OCP\IConfig;
50
use OCP\IGroupManager;
51
use OCP\IL10N;
52
use OCP\ILogger;
53
use OCP\IURLGenerator;
54
use OCP\IUser;
55
use OCP\IUserManager;
56
use OCP\L10N\IFactory;
57
use OCP\Mail\IMailer;
58
use OCP\Security\IHasher;
59
use OCP\Security\ISecureRandom;
60
use OCP\Share\Exceptions\GenericShareException;
61
use OCP\Share\Exceptions\ShareNotFound;
62
use OCP\Share\IManager;
63
use OCP\Share\IProviderFactory;
64
use OCP\Share\IShare;
65
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
66
use Symfony\Component\EventDispatcher\GenericEvent;
67
use OCP\Share\IShareProvider;
68
use OCP\Share;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, OC\Share20\Share. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
69
70
/**
71
 * This class is the communication hub for all sharing related operations.
72
 */
73
class Manager implements IManager {
74
75
	/** @var IProviderFactory */
76
	private $factory;
77
	/** @var ILogger */
78
	private $logger;
79
	/** @var IConfig */
80
	private $config;
81
	/** @var ISecureRandom */
82
	private $secureRandom;
83
	/** @var IHasher */
84
	private $hasher;
85
	/** @var IMountManager */
86
	private $mountManager;
87
	/** @var IGroupManager */
88
	private $groupManager;
89
	/** @var IL10N */
90
	private $l;
91
	/** @var IFactory */
92
	private $l10nFactory;
93
	/** @var IUserManager */
94
	private $userManager;
95
	/** @var IRootFolder */
96
	private $rootFolder;
97
	/** @var CappedMemoryCache */
98
	private $sharingDisabledForUsersCache;
99
	/** @var EventDispatcherInterface */
100
	private $eventDispatcher;
101
	/** @var LegacyHooks */
102
	private $legacyHooks;
103
	/** @var IMailer */
104
	private $mailer;
105
	/** @var IURLGenerator */
106
	private $urlGenerator;
107
	/** @var \OC_Defaults */
108
	private $defaults;
109
110
111
	/**
112
	 * Manager constructor.
113
	 *
114
	 * @param ILogger $logger
115
	 * @param IConfig $config
116
	 * @param ISecureRandom $secureRandom
117
	 * @param IHasher $hasher
118
	 * @param IMountManager $mountManager
119
	 * @param IGroupManager $groupManager
120
	 * @param IL10N $l
121
	 * @param IFactory $l10nFactory
122
	 * @param IProviderFactory $factory
123
	 * @param IUserManager $userManager
124
	 * @param IRootFolder $rootFolder
125
	 * @param EventDispatcherInterface $eventDispatcher
126
	 * @param IMailer $mailer
127
	 * @param IURLGenerator $urlGenerator
128
	 * @param \OC_Defaults $defaults
129
	 */
130
	public function __construct(
131
			ILogger $logger,
132
			IConfig $config,
133
			ISecureRandom $secureRandom,
134
			IHasher $hasher,
135
			IMountManager $mountManager,
136
			IGroupManager $groupManager,
137
			IL10N $l,
138
			IFactory $l10nFactory,
139
			IProviderFactory $factory,
140
			IUserManager $userManager,
141
			IRootFolder $rootFolder,
142
			EventDispatcherInterface $eventDispatcher,
143
			IMailer $mailer,
144
			IURLGenerator $urlGenerator,
145
			\OC_Defaults $defaults
146
	) {
147
		$this->logger = $logger;
148
		$this->config = $config;
149
		$this->secureRandom = $secureRandom;
150
		$this->hasher = $hasher;
151
		$this->mountManager = $mountManager;
152
		$this->groupManager = $groupManager;
153
		$this->l = $l;
154
		$this->l10nFactory = $l10nFactory;
155
		$this->factory = $factory;
156
		$this->userManager = $userManager;
157
		$this->rootFolder = $rootFolder;
158
		$this->eventDispatcher = $eventDispatcher;
159
		$this->sharingDisabledForUsersCache = new CappedMemoryCache();
160
		$this->legacyHooks = new LegacyHooks($this->eventDispatcher);
161
		$this->mailer = $mailer;
162
		$this->urlGenerator = $urlGenerator;
163
		$this->defaults = $defaults;
164
	}
165
166
	/**
167
	 * Convert from a full share id to a tuple (providerId, shareId)
168
	 *
169
	 * @param string $id
170
	 * @return string[]
171
	 */
172
	private function splitFullId($id) {
173
		return explode(':', $id, 2);
174
	}
175
176
	/**
177
	 * Verify if a password meets all requirements
178
	 *
179
	 * @param string $password
180
	 * @throws \Exception
181
	 */
182
	protected function verifyPassword($password) {
183
		if ($password === null) {
0 ignored issues
show
introduced by
The condition $password === null is always false.
Loading history...
184
			// No password is set, check if this is allowed.
185
			if ($this->shareApiLinkEnforcePassword()) {
186
				throw new \InvalidArgumentException('Passwords are enforced for link shares');
187
			}
188
189
			return;
190
		}
191
192
		// Let others verify the password
193
		try {
194
			$event = new GenericEvent($password);
195
			$this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event);
0 ignored issues
show
Bug introduced by
'OCP\PasswordPolicy::validate' of type string is incompatible with the type object expected by parameter $event of Symfony\Contracts\EventD...erInterface::dispatch(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

195
			$this->eventDispatcher->dispatch(/** @scrutinizer ignore-type */ 'OCP\PasswordPolicy::validate', $event);
Loading history...
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with $event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

195
			$this->eventDispatcher->/** @scrutinizer ignore-call */ 
196
                           dispatch('OCP\PasswordPolicy::validate', $event);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
196
		} catch (HintException $e) {
197
			throw new \Exception($e->getHint());
198
		}
199
	}
200
201
	/**
202
	 * Check for generic requirements before creating a share
203
	 *
204
	 * @param \OCP\Share\IShare $share
205
	 * @throws \InvalidArgumentException
206
	 * @throws GenericShareException
207
	 *
208
	 * @suppress PhanUndeclaredClassMethod
209
	 */
210
	protected function generalCreateChecks(\OCP\Share\IShare $share) {
211
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_USER has been deprecated: 17.0.0 - use IShare::TYPE_USER instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

211
		if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_USER) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
212
			// We expect a valid user as sharedWith for user shares
213
			if (!$this->userManager->userExists($share->getSharedWith())) {
214
				throw new \InvalidArgumentException('SharedWith is not a valid user');
215
			}
216
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_GROUP has been deprecated: 17.0.0 - use IShare::TYPE_GROUP instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

216
		} else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_GROUP) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
217
			// We expect a valid group as sharedWith for group shares
218
			if (!$this->groupManager->groupExists($share->getSharedWith())) {
219
				throw new \InvalidArgumentException('SharedWith is not a valid group');
220
			}
221
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_LINK has been deprecated: 17.0.0 - use IShare::TYPE_LINK instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

221
		} else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_LINK) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
222
			if ($share->getSharedWith() !== null) {
0 ignored issues
show
introduced by
The condition $share->getSharedWith() !== null is always true.
Loading history...
223
				throw new \InvalidArgumentException('SharedWith should be empty');
224
			}
225
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_REMOTE has been deprecated: 17.0.0 - use IShare::TYPE_REMOTE instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

225
		} else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_REMOTE) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
226
			if ($share->getSharedWith() === null) {
0 ignored issues
show
introduced by
The condition $share->getSharedWith() === null is always false.
Loading history...
227
				throw new \InvalidArgumentException('SharedWith should not be empty');
228
			}
229
		}  else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_REMOTE_GROUP has been deprecated: 17.0.0 - use IShare::REMOTE_GROUP instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

229
		}  else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
230
			if ($share->getSharedWith() === null) {
0 ignored issues
show
introduced by
The condition $share->getSharedWith() === null is always false.
Loading history...
231
				throw new \InvalidArgumentException('SharedWith should not be empty');
232
			}
233
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

233
		} else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
234
			if ($share->getSharedWith() === null) {
0 ignored issues
show
introduced by
The condition $share->getSharedWith() === null is always false.
Loading history...
235
				throw new \InvalidArgumentException('SharedWith should not be empty');
236
			}
237
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_CIRCLE has been deprecated: 17.0.0 - use IShare::TYPE_CIRCLE instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

237
		} else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_CIRCLE) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
238
			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($share->getSharedWith());
0 ignored issues
show
Bug introduced by
The type OCA\Circles\Api\v1\Circles was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
239
			if ($circle === null) {
240
				throw new \InvalidArgumentException('SharedWith is not a valid circle');
241
			}
242
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_ROOM) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_ROOM has been deprecated: 17.0.0 - use IShare::TYPE_ROOM instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

242
		} else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_ROOM) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
243
		} else {
244
			// We can't handle other types yet
245
			throw new \InvalidArgumentException('unknown share type');
246
		}
247
248
		// Verify the initiator of the share is set
249
		if ($share->getSharedBy() === null) {
0 ignored issues
show
introduced by
The condition $share->getSharedBy() === null is always false.
Loading history...
250
			throw new \InvalidArgumentException('SharedBy should be set');
251
		}
252
253
		// Cannot share with yourself
254
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_USER has been deprecated: 17.0.0 - use IShare::TYPE_USER instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

254
		if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_USER &&

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
255
			$share->getSharedWith() === $share->getSharedBy()) {
256
			throw new \InvalidArgumentException('Can’t share with yourself');
257
		}
258
259
		// The path should be set
260
		if ($share->getNode() === null) {
261
			throw new \InvalidArgumentException('Path should be set');
262
		}
263
264
		// And it should be a file or a folder
265
		if (!($share->getNode() instanceof \OCP\Files\File) &&
266
				!($share->getNode() instanceof \OCP\Files\Folder)) {
0 ignored issues
show
introduced by
$share->getNode() is always a sub-type of OCP\Files\Folder.
Loading history...
267
			throw new \InvalidArgumentException('Path should be either a file or a folder');
268
		}
269
270
		// And you can't share your rootfolder
271
		if ($this->userManager->userExists($share->getSharedBy())) {
272
			$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
273
			$userFolderPath = $userFolder->getPath();
274
		} else {
275
			$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
276
			$userFolderPath = $userFolder->getPath();
277
		}
278
		if ($userFolderPath === $share->getNode()->getPath()) {
279
			throw new \InvalidArgumentException('You can’t share your root folder');
280
		}
281
282
		// Check if we actually have share permissions
283
		if (!$share->getNode()->isShareable()) {
284
			$message_t = $this->l->t('You are not allowed to share %s', [$share->getNode()->getPath()]);
285
			throw new GenericShareException($message_t, $message_t, 404);
286
		}
287
288
		// Permissions should be set
289
		if ($share->getPermissions() === null) {
0 ignored issues
show
introduced by
The condition $share->getPermissions() === null is always false.
Loading history...
290
			throw new \InvalidArgumentException('A share requires permissions');
291
		}
292
293
		$isFederatedShare = $share->getNode()->getStorage()->instanceOfStorage('\OCA\Files_Sharing\External\Storage');
294
		$permissions = 0;
295
		$mount = $share->getNode()->getMountPoint();
296
		if (!$isFederatedShare && $share->getNode()->getOwner()->getUID() !== $share->getSharedBy()) {
297
			// When it's a reshare use the parent share permissions as maximum
298
			$userMountPointId = $mount->getStorageRootId();
299
			$userMountPoints = $userFolder->getById($userMountPointId);
300
			$userMountPoint = array_shift($userMountPoints);
301
302
			/* Check if this is an incoming share */
303
			$incomingShares = $this->getSharedWith($share->getSharedBy(), Share::SHARE_TYPE_USER, $userMountPoint, -1, 0);
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_USER has been deprecated: 17.0.0 - use IShare::TYPE_USER instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

303
			$incomingShares = $this->getSharedWith($share->getSharedBy(), /** @scrutinizer ignore-deprecated */ Share::SHARE_TYPE_USER, $userMountPoint, -1, 0);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
304
			$incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), Share::SHARE_TYPE_GROUP, $userMountPoint, -1, 0));
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_GROUP has been deprecated: 17.0.0 - use IShare::TYPE_GROUP instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

304
			$incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), /** @scrutinizer ignore-deprecated */ Share::SHARE_TYPE_GROUP, $userMountPoint, -1, 0));

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
305
			$incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), Share::SHARE_TYPE_CIRCLE, $userMountPoint, -1, 0));
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_CIRCLE has been deprecated: 17.0.0 - use IShare::TYPE_CIRCLE instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

305
			$incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), /** @scrutinizer ignore-deprecated */ Share::SHARE_TYPE_CIRCLE, $userMountPoint, -1, 0));

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
306
			$incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), Share::SHARE_TYPE_ROOM, $userMountPoint, -1, 0));
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_ROOM has been deprecated: 17.0.0 - use IShare::TYPE_ROOM instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

306
			$incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), /** @scrutinizer ignore-deprecated */ Share::SHARE_TYPE_ROOM, $userMountPoint, -1, 0));

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
307
308
			/** @var \OCP\Share\IShare[] $incomingShares */
309
			if (!empty($incomingShares)) {
310
				foreach ($incomingShares as $incomingShare) {
311
					$permissions |= $incomingShare->getPermissions();
312
				}
313
			}
314
		} else {
315
			/*
316
			 * Quick fix for #23536
317
			 * Non moveable mount points do not have update and delete permissions
318
			 * while we 'most likely' do have that on the storage.
319
			 */
320
			$permissions = $share->getNode()->getPermissions();
321
			if (!($mount instanceof MoveableMount)) {
322
				$permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
323
			}
324
		}
325
326
		// Check that we do not share with more permissions than we have
327
		if ($share->getPermissions() & ~$permissions) {
328
			$message_t = $this->l->t('Can’t increase permissions of %s', [$share->getNode()->getPath()]);
329
			throw new GenericShareException($message_t, $message_t, 404);
330
		}
331
332
333
		// Check that read permissions are always set
334
		// Link shares are allowed to have no read permissions to allow upload to hidden folders
335
		$noReadPermissionRequired = $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_LINK has been deprecated: 17.0.0 - use IShare::TYPE_LINK instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

335
		$noReadPermissionRequired = $share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_LINK

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
336
			|| $share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL;
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

336
			|| $share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL;

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
337
		if (!$noReadPermissionRequired &&
338
			($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
339
			throw new \InvalidArgumentException('Shares need at least read permissions');
340
		}
341
342
		if ($share->getNode() instanceof \OCP\Files\File) {
343
			if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
344
				$message_t = $this->l->t('Files can’t be shared with delete permissions');
345
				throw new GenericShareException($message_t);
346
			}
347
			if ($share->getPermissions() & \OCP\Constants::PERMISSION_CREATE) {
348
				$message_t = $this->l->t('Files can’t be shared with create permissions');
349
				throw new GenericShareException($message_t);
350
			}
351
		}
352
	}
353
354
	/**
355
	 * Validate if the expiration date fits the system settings
356
	 *
357
	 * @param \OCP\Share\IShare $share The share to validate the expiration date of
358
	 * @return \OCP\Share\IShare The modified share object
359
	 * @throws GenericShareException
360
	 * @throws \InvalidArgumentException
361
	 * @throws \Exception
362
	 */
363
	protected function validateExpirationDate(\OCP\Share\IShare $share) {
364
365
		$expirationDate = $share->getExpirationDate();
366
367
		if ($expirationDate !== null) {
368
			//Make sure the expiration date is a date
369
			$expirationDate->setTime(0, 0, 0);
370
371
			$date = new \DateTime();
372
			$date->setTime(0, 0, 0);
373
			if ($date >= $expirationDate) {
374
				$message = $this->l->t('Expiration date is in the past');
375
				throw new GenericShareException($message, $message, 404);
376
			}
377
		}
378
379
		// If expiredate is empty set a default one if there is a default
380
		$fullId = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $fullId is dead and can be removed.
Loading history...
381
		try {
382
			$fullId = $share->getFullId();
383
		} catch (\UnexpectedValueException $e) {
384
			// This is a new share
385
		}
386
387
		if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
0 ignored issues
show
introduced by
The condition $fullId === null is always false.
Loading history...
388
			$expirationDate = new \DateTime();
389
			$expirationDate->setTime(0,0,0);
390
			$expirationDate->add(new \DateInterval('P'.$this->shareApiLinkDefaultExpireDays().'D'));
391
		}
392
393
		// If we enforce the expiration date check that is does not exceed
394
		if ($this->shareApiLinkDefaultExpireDateEnforced()) {
395
			if ($expirationDate === null) {
396
				throw new \InvalidArgumentException('Expiration date is enforced');
397
			}
398
399
			$date = new \DateTime();
400
			$date->setTime(0, 0, 0);
401
			$date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
402
			if ($date < $expirationDate) {
403
				$message = $this->l->t('Can’t set expiration date more than %s days in the future', [$this->shareApiLinkDefaultExpireDays()]);
404
				throw new GenericShareException($message, $message, 404);
405
			}
406
		}
407
408
		$accepted = true;
409
		$message = '';
410
		\OCP\Util::emitHook('\OC\Share', 'verifyExpirationDate', [
411
			'expirationDate' => &$expirationDate,
412
			'accepted' => &$accepted,
413
			'message' => &$message,
414
			'passwordSet' => $share->getPassword() !== null,
415
		]);
416
417
		if (!$accepted) {
0 ignored issues
show
introduced by
The condition $accepted is always true.
Loading history...
418
			throw new \Exception($message);
419
		}
420
421
		$share->setExpirationDate($expirationDate);
422
423
		return $share;
424
	}
425
426
	/**
427
	 * Check for pre share requirements for user shares
428
	 *
429
	 * @param \OCP\Share\IShare $share
430
	 * @throws \Exception
431
	 */
432
	protected function userCreateChecks(\OCP\Share\IShare $share) {
433
		// Check if we can share with group members only
434
		if ($this->shareWithGroupMembersOnly()) {
435
			$sharedBy = $this->userManager->get($share->getSharedBy());
436
			$sharedWith = $this->userManager->get($share->getSharedWith());
437
			// Verify we can share with this user
438
			$groups = array_intersect(
439
					$this->groupManager->getUserGroupIds($sharedBy),
440
					$this->groupManager->getUserGroupIds($sharedWith)
441
			);
442
			if (empty($groups)) {
443
				throw new \Exception('Sharing is only allowed with group members');
444
			}
445
		}
446
447
		/*
448
		 * TODO: Could be costly, fix
449
		 *
450
		 * Also this is not what we want in the future.. then we want to squash identical shares.
451
		 */
452
		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_USER);
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_USER has been deprecated: 17.0.0 - use IShare::TYPE_USER instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

452
		$provider = $this->factory->getProviderForType(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_USER);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
453
		$existingShares = $provider->getSharesByPath($share->getNode());
454
		foreach($existingShares as $existingShare) {
455
			// Ignore if it is the same share
456
			try {
457
				if ($existingShare->getFullId() === $share->getFullId()) {
458
					continue;
459
				}
460
			} catch (\UnexpectedValueException $e) {
461
				//Shares are not identical
462
			}
463
464
			// Identical share already existst
465
			if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
466
				throw new \Exception('Path is already shared with this user');
467
			}
468
469
			// The share is already shared with this user via a group share
470
			if ($existingShare->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_GROUP has been deprecated: 17.0.0 - use IShare::TYPE_GROUP instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

470
			if ($existingShare->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_GROUP) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
471
				$group = $this->groupManager->get($existingShare->getSharedWith());
472
				if (!is_null($group)) {
473
					$user = $this->userManager->get($share->getSharedWith());
474
475
					if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
476
						throw new \Exception('Path is already shared with this user');
477
					}
478
				}
479
			}
480
		}
481
	}
482
483
	/**
484
	 * Check for pre share requirements for group shares
485
	 *
486
	 * @param \OCP\Share\IShare $share
487
	 * @throws \Exception
488
	 */
489
	protected function groupCreateChecks(\OCP\Share\IShare $share) {
490
		// Verify group shares are allowed
491
		if (!$this->allowGroupSharing()) {
492
			throw new \Exception('Group sharing is now allowed');
493
		}
494
495
		// Verify if the user can share with this group
496
		if ($this->shareWithGroupMembersOnly()) {
497
			$sharedBy = $this->userManager->get($share->getSharedBy());
498
			$sharedWith = $this->groupManager->get($share->getSharedWith());
499
			if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
500
				throw new \Exception('Sharing is only allowed within your own groups');
501
			}
502
		}
503
504
		/*
505
		 * TODO: Could be costly, fix
506
		 *
507
		 * Also this is not what we want in the future.. then we want to squash identical shares.
508
		 */
509
		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_GROUP has been deprecated: 17.0.0 - use IShare::TYPE_GROUP instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

509
		$provider = $this->factory->getProviderForType(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_GROUP);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
510
		$existingShares = $provider->getSharesByPath($share->getNode());
511
		foreach($existingShares as $existingShare) {
512
			try {
513
				if ($existingShare->getFullId() === $share->getFullId()) {
514
					continue;
515
				}
516
			} catch (\UnexpectedValueException $e) {
517
				//It is a new share so just continue
518
			}
519
520
			if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
521
				throw new \Exception('Path is already shared with this group');
522
			}
523
		}
524
	}
525
526
	/**
527
	 * Check for pre share requirements for link shares
528
	 *
529
	 * @param \OCP\Share\IShare $share
530
	 * @throws \Exception
531
	 */
532
	protected function linkCreateChecks(\OCP\Share\IShare $share) {
533
		// Are link shares allowed?
534
		if (!$this->shareApiAllowLinks()) {
535
			throw new \Exception('Link sharing is not allowed');
536
		}
537
538
		// Link shares by definition can't have share permissions
539
		if ($share->getPermissions() & \OCP\Constants::PERMISSION_SHARE) {
540
			throw new \InvalidArgumentException('Link shares can’t have reshare permissions');
541
		}
542
543
		// Check if public upload is allowed
544
		if (!$this->shareApiLinkAllowPublicUpload() &&
545
			($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) {
546
			throw new \InvalidArgumentException('Public upload is not allowed');
547
		}
548
	}
549
550
	/**
551
	 * To make sure we don't get invisible link shares we set the parent
552
	 * of a link if it is a reshare. This is a quick word around
553
	 * until we can properly display multiple link shares in the UI
554
	 *
555
	 * See: https://github.com/owncloud/core/issues/22295
556
	 *
557
	 * FIXME: Remove once multiple link shares can be properly displayed
558
	 *
559
	 * @param \OCP\Share\IShare $share
560
	 */
561
	protected function setLinkParent(\OCP\Share\IShare $share) {
562
563
		// No sense in checking if the method is not there.
564
		if (method_exists($share, 'setParent')) {
565
			$storage = $share->getNode()->getStorage();
566
			if ($storage->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
567
				/** @var \OCA\Files_Sharing\SharedStorage $storage */
568
				$share->setParent($storage->getShareId());
569
			}
570
		}
571
	}
572
573
	/**
574
	 * @param File|Folder $path
575
	 */
576
	protected function pathCreateChecks($path) {
577
		// Make sure that we do not share a path that contains a shared mountpoint
578
		if ($path instanceof \OCP\Files\Folder) {
579
			$mounts = $this->mountManager->findIn($path->getPath());
580
			foreach($mounts as $mount) {
581
				if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
582
					throw new \InvalidArgumentException('Path contains files shared with you');
583
				}
584
			}
585
		}
586
	}
587
588
	/**
589
	 * Check if the user that is sharing can actually share
590
	 *
591
	 * @param \OCP\Share\IShare $share
592
	 * @throws \Exception
593
	 */
594
	protected function canShare(\OCP\Share\IShare $share) {
595
		if (!$this->shareApiEnabled()) {
596
			throw new \Exception('Sharing is disabled');
597
		}
598
599
		if ($this->sharingDisabledForUser($share->getSharedBy())) {
600
			throw new \Exception('Sharing is disabled for you');
601
		}
602
	}
603
604
	/**
605
	 * Share a path
606
	 *
607
	 * @param \OCP\Share\IShare $share
608
	 * @return Share The share object
609
	 * @throws \Exception
610
	 *
611
	 * TODO: handle link share permissions or check them
612
	 */
613
	public function createShare(\OCP\Share\IShare $share) {
614
		$this->canShare($share);
615
616
		$this->generalCreateChecks($share);
617
618
		// Verify if there are any issues with the path
619
		$this->pathCreateChecks($share->getNode());
620
621
		/*
622
		 * On creation of a share the owner is always the owner of the path
623
		 * Except for mounted federated shares.
624
		 */
625
		$storage = $share->getNode()->getStorage();
626
		if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
627
			$parent = $share->getNode()->getParent();
628
			while($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
629
				$parent = $parent->getParent();
630
			}
631
			$share->setShareOwner($parent->getOwner()->getUID());
632
		} else {
633
			$share->setShareOwner($share->getNode()->getOwner()->getUID());
634
		}
635
636
		//Verify share type
637
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_USER has been deprecated: 17.0.0 - use IShare::TYPE_USER instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

637
		if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_USER) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
638
			$this->userCreateChecks($share);
639
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_GROUP has been deprecated: 17.0.0 - use IShare::TYPE_GROUP instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

639
		} else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_GROUP) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
640
			$this->groupCreateChecks($share);
641
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_LINK has been deprecated: 17.0.0 - use IShare::TYPE_LINK instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

641
		} else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_LINK) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
642
			$this->linkCreateChecks($share);
643
			$this->setLinkParent($share);
644
645
			/*
646
			 * For now ignore a set token.
647
			 */
648
			$share->setToken(
649
				$this->secureRandom->generate(
650
					\OC\Share\Constants::TOKEN_LENGTH,
651
					\OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
652
				)
653
			);
654
655
			//Verify the expiration date
656
			$this->validateExpirationDate($share);
657
658
			//Verify the password
659
			$this->verifyPassword($share->getPassword());
660
661
			// If a password is set. Hash it!
662
			if ($share->getPassword() !== null) {
0 ignored issues
show
introduced by
The condition $share->getPassword() !== null is always true.
Loading history...
663
				$share->setPassword($this->hasher->hash($share->getPassword()));
664
			}
665
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

665
		} else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
666
			$share->setToken(
667
				$this->secureRandom->generate(
668
					\OC\Share\Constants::TOKEN_LENGTH,
669
					\OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
670
				)
671
			);
672
		}
673
674
		// Cannot share with the owner
675
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_USER has been deprecated: 17.0.0 - use IShare::TYPE_USER instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

675
		if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_USER &&

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
676
			$share->getSharedWith() === $share->getShareOwner()) {
677
			throw new \InvalidArgumentException('Can’t share with the share owner');
678
		}
679
680
		// Generate the target
681
		$target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getNode()->getName();
682
		$target = \OC\Files\Filesystem::normalizePath($target);
683
		$share->setTarget($target);
684
685
		// Pre share event
686
		$event = new GenericEvent($share);
687
		$this->eventDispatcher->dispatch('OCP\Share::preShare', $event);
0 ignored issues
show
Bug introduced by
'OCP\Share::preShare' of type string is incompatible with the type object expected by parameter $event of Symfony\Contracts\EventD...erInterface::dispatch(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

687
		$this->eventDispatcher->dispatch(/** @scrutinizer ignore-type */ 'OCP\Share::preShare', $event);
Loading history...
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with $event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

687
		$this->eventDispatcher->/** @scrutinizer ignore-call */ 
688
                          dispatch('OCP\Share::preShare', $event);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
688
		if ($event->isPropagationStopped() && $event->hasArgument('error')) {
0 ignored issues
show
Deprecated Code introduced by
The function Symfony\Component\EventD...:isPropagationStopped() has been deprecated: since Symfony 4.3, use "Symfony\Contracts\EventDispatcher\Event" instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

688
		if (/** @scrutinizer ignore-deprecated */ $event->isPropagationStopped() && $event->hasArgument('error')) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
689
			throw new \Exception($event->getArgument('error'));
690
		}
691
692
		$oldShare = $share;
693
		$provider = $this->factory->getProviderForType($share->getShareType());
694
		$share = $provider->create($share);
695
		//reuse the node we already have
696
		$share->setNode($oldShare->getNode());
697
698
		// Post share event
699
		$event = new GenericEvent($share);
700
		$this->eventDispatcher->dispatch('OCP\Share::postShare', $event);
701
702
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_USER has been deprecated: 17.0.0 - use IShare::TYPE_USER instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

702
		if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_USER) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
703
			$mailSend = $share->getMailSend();
704
			if($mailSend === true) {
705
				$user = $this->userManager->get($share->getSharedWith());
706
				if ($user !== null) {
707
					$emailAddress = $user->getEMailAddress();
708
					if ($emailAddress !== null && $emailAddress !== '') {
709
						$userLang = $this->config->getUserValue($share->getSharedWith(), 'core', 'lang', null);
710
						$l = $this->l10nFactory->get('lib', $userLang);
711
						$this->sendMailNotification(
712
							$l,
713
							$share->getNode()->getName(),
714
							$this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]),
715
							$share->getSharedBy(),
716
							$emailAddress,
717
							$share->getExpirationDate()
718
						);
719
						$this->logger->debug('Sent share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']);
720
					} else {
721
						$this->logger->debug('Share notification not sent to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']);
722
					}
723
				} else {
724
					$this->logger->debug('Share notification not sent to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']);
725
				}
726
			} else {
727
				$this->logger->debug('Share notification not sent because mailsend is false.', ['app' => 'share']);
728
			}
729
		}
730
731
		return $share;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $share returns the type OCP\Share\IShare which is incompatible with the documented return type OCP\Share.
Loading history...
732
	}
733
734
	/**
735
	 * Send mail notifications
736
	 *
737
	 * This method will catch and log mail transmission errors
738
	 *
739
	 * @param IL10N $l Language of the recipient
740
	 * @param string $filename file/folder name
741
	 * @param string $link link to the file/folder
742
	 * @param string $initiator user ID of share sender
743
	 * @param string $shareWith email address of share receiver
744
	 * @param \DateTime|null $expiration
745
	 */
746
	protected function sendMailNotification(IL10N $l,
747
											$filename,
748
											$link,
749
											$initiator,
750
											$shareWith,
751
											\DateTime $expiration = null) {
752
		$initiatorUser = $this->userManager->get($initiator);
753
		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
754
755
		$message = $this->mailer->createMessage();
756
757
		$emailTemplate = $this->mailer->createEMailTemplate('files_sharing.RecipientNotification', [
758
			'filename' => $filename,
759
			'link' => $link,
760
			'initiator' => $initiatorDisplayName,
761
			'expiration' => $expiration,
762
			'shareWith' => $shareWith,
763
		]);
764
765
		$emailTemplate->setSubject($l->t('%1$s shared »%2$s« with you', array($initiatorDisplayName, $filename)));
766
		$emailTemplate->addHeader();
767
		$emailTemplate->addHeading($l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
768
		$text = $l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
769
770
		$emailTemplate->addBodyText(
771
			htmlspecialchars($text . ' ' . $l->t('Click the button below to open it.')),
772
			$text
773
		);
774
		$emailTemplate->addBodyButton(
775
			$l->t('Open »%s«', [$filename]),
776
			$link
777
		);
778
779
		$message->setTo([$shareWith]);
780
781
		// The "From" contains the sharers name
782
		$instanceName = $this->defaults->getName();
783
		$senderName = $l->t(
784
			'%1$s via %2$s',
785
			[
786
				$initiatorDisplayName,
787
				$instanceName
788
			]
789
		);
790
		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
791
792
		// The "Reply-To" is set to the sharer if an mail address is configured
793
		// also the default footer contains a "Do not reply" which needs to be adjusted.
794
		$initiatorEmail = $initiatorUser->getEMailAddress();
795
		if($initiatorEmail !== null) {
796
			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
797
			$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
798
		} else {
799
			$emailTemplate->addFooter();
800
		}
801
802
		$message->useTemplate($emailTemplate);
803
		try {
804
			$failedRecipients = $this->mailer->send($message);
805
			if(!empty($failedRecipients)) {
806
				$this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients));
807
				return;
808
			}
809
		} catch (\Exception $e) {
810
			$this->logger->logException($e, ['message' => 'Share notification mail could not be sent']);
811
		}
812
	}
813
814
	/**
815
	 * Update a share
816
	 *
817
	 * @param \OCP\Share\IShare $share
818
	 * @return \OCP\Share\IShare The share object
819
	 * @throws \InvalidArgumentException
820
	 */
821
	public function updateShare(\OCP\Share\IShare $share) {
822
		$expirationDateUpdated = false;
823
824
		$this->canShare($share);
825
826
		try {
827
			$originalShare = $this->getShareById($share->getFullId());
828
		} catch (\UnexpectedValueException $e) {
829
			throw new \InvalidArgumentException('Share does not have a full id');
830
		}
831
832
		// We can't change the share type!
833
		if ($share->getShareType() !== $originalShare->getShareType()) {
834
			throw new \InvalidArgumentException('Can’t change share type');
835
		}
836
837
		// We can only change the recipient on user shares
838
		if ($share->getSharedWith() !== $originalShare->getSharedWith() &&
839
		    $share->getShareType() !== \OCP\Share::SHARE_TYPE_USER) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_USER has been deprecated: 17.0.0 - use IShare::TYPE_USER instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

839
		    $share->getShareType() !== /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_USER) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
840
			throw new \InvalidArgumentException('Can only update recipient on user shares');
841
		}
842
843
		// Cannot share with the owner
844
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_USER has been deprecated: 17.0.0 - use IShare::TYPE_USER instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

844
		if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_USER &&

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
845
			$share->getSharedWith() === $share->getShareOwner()) {
846
			throw new \InvalidArgumentException('Can’t share with the share owner');
847
		}
848
849
		$this->generalCreateChecks($share);
850
851
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_USER has been deprecated: 17.0.0 - use IShare::TYPE_USER instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

851
		if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_USER) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
852
			$this->userCreateChecks($share);
853
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_GROUP has been deprecated: 17.0.0 - use IShare::TYPE_GROUP instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

853
		} else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_GROUP) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
854
			$this->groupCreateChecks($share);
855
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_LINK has been deprecated: 17.0.0 - use IShare::TYPE_LINK instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

855
		} else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_LINK) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
856
			$this->linkCreateChecks($share);
857
858
			$this->updateSharePasswordIfNeeded($share, $originalShare);
859
860
			if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
861
				//Verify the expiration date
862
				$this->validateExpirationDate($share);
863
				$expirationDateUpdated = true;
864
			}
865
		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

865
		} else if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
866
			// The new password is not set again if it is the same as the old
867
			// one, unless when switching from sending by Talk to sending by
868
			// mail.
869
			$plainTextPassword = $share->getPassword();
870
			if (!empty($plainTextPassword) && !$this->updateSharePasswordIfNeeded($share, $originalShare) &&
871
					!($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk())) {
872
				$plainTextPassword = null;
873
			}
874
			if (empty($plainTextPassword) && !$originalShare->getSendPasswordByTalk() && $share->getSendPasswordByTalk()) {
875
				// If the same password was already sent by mail the recipient
876
				// would already have access to the share without having to call
877
				// the sharer to verify her identity
878
				throw new \InvalidArgumentException('Can’t enable sending the password by Talk without setting a new password');
879
			}
880
		}
881
882
		$this->pathCreateChecks($share->getNode());
883
884
		// Now update the share!
885
		$provider = $this->factory->getProviderForType($share->getShareType());
886
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

886
		if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
887
			$share = $provider->update($share, $plainTextPassword);
0 ignored issues
show
Unused Code introduced by
The call to OCP\Share\IShareProvider::update() has too many arguments starting with $plainTextPassword. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

887
			/** @scrutinizer ignore-call */ 
888
   $share = $provider->update($share, $plainTextPassword);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
Comprehensibility Best Practice introduced by
The variable $plainTextPassword does not seem to be defined for all execution paths leading up to this point.
Loading history...
888
		} else {
889
			$share = $provider->update($share);
890
		}
891
892
		if ($expirationDateUpdated === true) {
893
			\OC_Hook::emit(Share::class, 'post_set_expiration_date', [
894
				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
895
				'itemSource' => $share->getNode()->getId(),
896
				'date' => $share->getExpirationDate(),
897
				'uidOwner' => $share->getSharedBy(),
898
			]);
899
		}
900
901
		if ($share->getPassword() !== $originalShare->getPassword()) {
902
			\OC_Hook::emit(Share::class, 'post_update_password', [
903
				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
904
				'itemSource' => $share->getNode()->getId(),
905
				'uidOwner' => $share->getSharedBy(),
906
				'token' => $share->getToken(),
907
				'disabled' => is_null($share->getPassword()),
908
			]);
909
		}
910
911
		if ($share->getPermissions() !== $originalShare->getPermissions()) {
912
			if ($this->userManager->userExists($share->getShareOwner())) {
913
				$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
914
			} else {
915
				$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
916
			}
917
			\OC_Hook::emit(Share::class, 'post_update_permissions', array(
918
				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
919
				'itemSource' => $share->getNode()->getId(),
920
				'shareType' => $share->getShareType(),
921
				'shareWith' => $share->getSharedWith(),
922
				'uidOwner' => $share->getSharedBy(),
923
				'permissions' => $share->getPermissions(),
924
				'path' => $userFolder->getRelativePath($share->getNode()->getPath()),
925
			));
926
		}
927
928
		return $share;
929
	}
930
931
	/**
932
	 * Accept a share.
933
	 *
934
	 * @param IShare $share
935
	 * @param string $recipientId
936
	 * @return IShare The share object
937
	 * @throws \InvalidArgumentException
938
	 * @since 9.0.0
939
	 */
940
	public function acceptShare(IShare $share, string $recipientId): IShare {
941
		[$providerId, ] = $this->splitFullId($share->getFullId());
942
		$provider = $this->factory->getProvider($providerId);
943
944
		if (!method_exists($provider, 'acceptShare')) {
945
			// TODO FIX ME
946
			throw new \InvalidArgumentException('Share provider does not support accepting');
947
		}
948
		$provider->acceptShare($share, $recipientId);
949
		$event = new GenericEvent($share);
950
		$this->eventDispatcher->dispatch('OCP\Share::postAcceptShare', $event);
0 ignored issues
show
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with $event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

950
		$this->eventDispatcher->/** @scrutinizer ignore-call */ 
951
                          dispatch('OCP\Share::postAcceptShare', $event);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
Bug introduced by
'OCP\Share::postAcceptShare' of type string is incompatible with the type object expected by parameter $event of Symfony\Contracts\EventD...erInterface::dispatch(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

950
		$this->eventDispatcher->dispatch(/** @scrutinizer ignore-type */ 'OCP\Share::postAcceptShare', $event);
Loading history...
951
952
		return $share;
953
	}
954
955
	/**
956
	 * Updates the password of the given share if it is not the same as the
957
	 * password of the original share.
958
	 *
959
	 * @param \OCP\Share\IShare $share the share to update its password.
960
	 * @param \OCP\Share\IShare $originalShare the original share to compare its
961
	 *        password with.
962
	 * @return boolean whether the password was updated or not.
963
	 */
964
	private function updateSharePasswordIfNeeded(\OCP\Share\IShare $share, \OCP\Share\IShare $originalShare) {
965
		// Password updated.
966
		if ($share->getPassword() !== $originalShare->getPassword()) {
967
			//Verify the password
968
			$this->verifyPassword($share->getPassword());
969
970
			// If a password is set. Hash it!
971
			if ($share->getPassword() !== null) {
0 ignored issues
show
introduced by
The condition $share->getPassword() !== null is always true.
Loading history...
972
				$share->setPassword($this->hasher->hash($share->getPassword()));
973
974
				return true;
975
			}
976
		}
977
978
		return false;
979
	}
980
981
	/**
982
	 * Delete all the children of this share
983
	 * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
984
	 *
985
	 * @param \OCP\Share\IShare $share
986
	 * @return \OCP\Share\IShare[] List of deleted shares
987
	 */
988
	protected function deleteChildren(\OCP\Share\IShare $share) {
989
		$deletedShares = [];
990
991
		$provider = $this->factory->getProviderForType($share->getShareType());
992
993
		foreach ($provider->getChildren($share) as $child) {
0 ignored issues
show
Bug introduced by
The method getChildren() does not exist on OCP\Share\IShareProvider. Since it exists in all sub-types, consider adding an abstract or default implementation to OCP\Share\IShareProvider. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

993
		foreach ($provider->/** @scrutinizer ignore-call */ getChildren($share) as $child) {
Loading history...
994
			$deletedChildren = $this->deleteChildren($child);
995
			$deletedShares = array_merge($deletedShares, $deletedChildren);
996
997
			$provider->delete($child);
998
			$deletedShares[] = $child;
999
		}
1000
1001
		return $deletedShares;
1002
	}
1003
1004
	/**
1005
	 * Delete a share
1006
	 *
1007
	 * @param \OCP\Share\IShare $share
1008
	 * @throws ShareNotFound
1009
	 * @throws \InvalidArgumentException
1010
	 */
1011
	public function deleteShare(\OCP\Share\IShare $share) {
1012
1013
		try {
1014
			$share->getFullId();
1015
		} catch (\UnexpectedValueException $e) {
1016
			throw new \InvalidArgumentException('Share does not have a full id');
1017
		}
1018
1019
		$event = new GenericEvent($share);
1020
		$this->eventDispatcher->dispatch('OCP\Share::preUnshare', $event);
0 ignored issues
show
Bug introduced by
'OCP\Share::preUnshare' of type string is incompatible with the type object expected by parameter $event of Symfony\Contracts\EventD...erInterface::dispatch(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1020
		$this->eventDispatcher->dispatch(/** @scrutinizer ignore-type */ 'OCP\Share::preUnshare', $event);
Loading history...
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with $event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1020
		$this->eventDispatcher->/** @scrutinizer ignore-call */ 
1021
                          dispatch('OCP\Share::preUnshare', $event);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
1021
1022
		// Get all children and delete them as well
1023
		$deletedShares = $this->deleteChildren($share);
1024
1025
		// Do the actual delete
1026
		$provider = $this->factory->getProviderForType($share->getShareType());
1027
		$provider->delete($share);
1028
1029
		// All the deleted shares caused by this delete
1030
		$deletedShares[] = $share;
1031
1032
		// Emit post hook
1033
		$event->setArgument('deletedShares', $deletedShares);
1034
		$this->eventDispatcher->dispatch('OCP\Share::postUnshare', $event);
1035
	}
1036
1037
1038
	/**
1039
	 * Unshare a file as the recipient.
1040
	 * This can be different from a regular delete for example when one of
1041
	 * the users in a groups deletes that share. But the provider should
1042
	 * handle this.
1043
	 *
1044
	 * @param \OCP\Share\IShare $share
1045
	 * @param string $recipientId
1046
	 */
1047
	public function deleteFromSelf(\OCP\Share\IShare $share, $recipientId) {
1048
		list($providerId, ) = $this->splitFullId($share->getFullId());
1049
		$provider = $this->factory->getProvider($providerId);
1050
1051
		$provider->deleteFromSelf($share, $recipientId);
1052
		$event = new GenericEvent($share);
1053
		$this->eventDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event);
0 ignored issues
show
Bug introduced by
'OCP\Share::postUnshareFromSelf' of type string is incompatible with the type object expected by parameter $event of Symfony\Contracts\EventD...erInterface::dispatch(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1053
		$this->eventDispatcher->dispatch(/** @scrutinizer ignore-type */ 'OCP\Share::postUnshareFromSelf', $event);
Loading history...
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with $event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1053
		$this->eventDispatcher->/** @scrutinizer ignore-call */ 
1054
                          dispatch('OCP\Share::postUnshareFromSelf', $event);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
1054
	}
1055
1056
	public function restoreShare(IShare $share, string $recipientId): IShare {
1057
		list($providerId, ) = $this->splitFullId($share->getFullId());
1058
		$provider = $this->factory->getProvider($providerId);
1059
1060
		return $provider->restore($share, $recipientId);
1061
	}
1062
1063
	/**
1064
	 * @inheritdoc
1065
	 */
1066
	public function moveShare(\OCP\Share\IShare $share, $recipientId) {
1067
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_LINK has been deprecated: 17.0.0 - use IShare::TYPE_LINK instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1067
		if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_LINK) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1068
			throw new \InvalidArgumentException('Can’t change target of link share');
1069
		}
1070
1071
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() !== $recipientId) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_USER has been deprecated: 17.0.0 - use IShare::TYPE_USER instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1071
		if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() !== $recipientId) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1072
			throw new \InvalidArgumentException('Invalid recipient');
1073
		}
1074
1075
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_GROUP has been deprecated: 17.0.0 - use IShare::TYPE_GROUP instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1075
		if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_GROUP) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1076
			$sharedWith = $this->groupManager->get($share->getSharedWith());
1077
			if (is_null($sharedWith)) {
1078
				throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist');
1079
			}
1080
			$recipient = $this->userManager->get($recipientId);
1081
			if (!$sharedWith->inGroup($recipient)) {
1082
				throw new \InvalidArgumentException('Invalid recipient');
1083
			}
1084
		}
1085
1086
		list($providerId, ) = $this->splitFullId($share->getFullId());
1087
		$provider = $this->factory->getProvider($providerId);
1088
1089
		$provider->move($share, $recipientId);
1090
	}
1091
1092
	public function getSharesInFolder($userId, Folder $node, $reshares = false) {
1093
		$providers = $this->factory->getAllProviders();
1094
1095
		return array_reduce($providers, function($shares, IShareProvider $provider) use ($userId, $node, $reshares) {
1096
			$newShares = $provider->getSharesInFolder($userId, $node, $reshares);
1097
			foreach ($newShares as $fid => $data) {
1098
				if (!isset($shares[$fid])) {
1099
					$shares[$fid] = [];
1100
				}
1101
1102
				$shares[$fid] = array_merge($shares[$fid], $data);
0 ignored issues
show
Bug introduced by
$data of type OCP\Share\IShare is incompatible with the type array|null expected by parameter $array2 of array_merge(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1102
				$shares[$fid] = array_merge($shares[$fid], /** @scrutinizer ignore-type */ $data);
Loading history...
1103
			}
1104
			return $shares;
1105
		}, []);
1106
	}
1107
1108
	/**
1109
	 * @inheritdoc
1110
	 */
1111
	public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0) {
1112
		if ($path !== null &&
1113
				!($path instanceof \OCP\Files\File) &&
1114
				!($path instanceof \OCP\Files\Folder)) {
1115
			throw new \InvalidArgumentException('invalid path');
1116
		}
1117
1118
		try {
1119
			$provider = $this->factory->getProviderForType($shareType);
1120
		} catch (ProviderException $e) {
1121
			return [];
1122
		}
1123
1124
		$shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1125
1126
		/*
1127
		 * Work around so we don't return expired shares but still follow
1128
		 * proper pagination.
1129
		 */
1130
1131
		$shares2 = [];
1132
1133
		while(true) {
1134
			$added = 0;
1135
			foreach ($shares as $share) {
1136
1137
				try {
1138
					$this->checkExpireDate($share);
1139
				} catch (ShareNotFound $e) {
1140
					//Ignore since this basically means the share is deleted
1141
					continue;
1142
				}
1143
1144
				$added++;
1145
				$shares2[] = $share;
1146
1147
				if (count($shares2) === $limit) {
1148
					break;
1149
				}
1150
			}
1151
1152
			// If we did not fetch more shares than the limit then there are no more shares
1153
			if (count($shares) < $limit) {
1154
				break;
1155
			}
1156
1157
			if (count($shares2) === $limit) {
1158
				break;
1159
			}
1160
1161
			// If there was no limit on the select we are done
1162
			if ($limit === -1) {
1163
				break;
1164
			}
1165
1166
			$offset += $added;
1167
1168
			// Fetch again $limit shares
1169
			$shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1170
1171
			// No more shares means we are done
1172
			if (empty($shares)) {
1173
				break;
1174
			}
1175
		}
1176
1177
		$shares = $shares2;
1178
1179
		return $shares;
1180
	}
1181
1182
	/**
1183
	 * @inheritdoc
1184
	 */
1185
	public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1186
		try {
1187
			$provider = $this->factory->getProviderForType($shareType);
1188
		} catch (ProviderException $e) {
1189
			return [];
1190
		}
1191
1192
		$shares = $provider->getSharedWith($userId, $shareType, $node, $limit, $offset);
1193
1194
		// remove all shares which are already expired
1195
		foreach ($shares as $key => $share) {
1196
			try {
1197
				$this->checkExpireDate($share);
1198
			} catch (ShareNotFound $e) {
1199
				unset($shares[$key]);
1200
			}
1201
		}
1202
1203
		return $shares;
1204
	}
1205
1206
	/**
1207
	 * @inheritdoc
1208
	 */
1209
	public function getDeletedSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1210
		$shares = $this->getSharedWith($userId, $shareType, $node, $limit, $offset);
1211
1212
		// Only get deleted shares
1213
		$shares = array_filter($shares, function(IShare $share) {
1214
			return $share->getPermissions() === 0;
1215
		});
1216
1217
		// Only get shares where the owner still exists
1218
		$shares = array_filter($shares, function (IShare $share) {
1219
			return $this->userManager->userExists($share->getShareOwner());
1220
		});
1221
1222
		return $shares;
1223
	}
1224
1225
	/**
1226
	 * @inheritdoc
1227
	 */
1228
	public function getShareById($id, $recipient = null) {
1229
		if ($id === null) {
1230
			throw new ShareNotFound();
1231
		}
1232
1233
		list($providerId, $id) = $this->splitFullId($id);
1234
1235
		try {
1236
			$provider = $this->factory->getProvider($providerId);
1237
		} catch (ProviderException $e) {
1238
			throw new ShareNotFound();
1239
		}
1240
1241
		$share = $provider->getShareById($id, $recipient);
0 ignored issues
show
Bug introduced by
$id of type string is incompatible with the type integer expected by parameter $id of OCP\Share\IShareProvider::getShareById(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1241
		$share = $provider->getShareById(/** @scrutinizer ignore-type */ $id, $recipient);
Loading history...
1242
1243
		$this->checkExpireDate($share);
1244
1245
		return $share;
1246
	}
1247
1248
	/**
1249
	 * Get all the shares for a given path
1250
	 *
1251
	 * @param \OCP\Files\Node $path
1252
	 * @param int $page
1253
	 * @param int $perPage
1254
	 *
1255
	 * @return Share[]
1256
	 */
1257
	public function getSharesByPath(\OCP\Files\Node $path, $page=0, $perPage=50) {
0 ignored issues
show
Unused Code introduced by
The parameter $page is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1257
	public function getSharesByPath(\OCP\Files\Node $path, /** @scrutinizer ignore-unused */ $page=0, $perPage=50) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $path is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1257
	public function getSharesByPath(/** @scrutinizer ignore-unused */ \OCP\Files\Node $path, $page=0, $perPage=50) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $perPage is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1257
	public function getSharesByPath(\OCP\Files\Node $path, $page=0, /** @scrutinizer ignore-unused */ $perPage=50) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1258
		return [];
1259
	}
1260
1261
	/**
1262
	 * Get the share by token possible with password
1263
	 *
1264
	 * @param string $token
1265
	 * @return Share
1266
	 *
1267
	 * @throws ShareNotFound
1268
	 */
1269
	public function getShareByToken($token) {
1270
		// tokens can't be valid local user names
1271
		if ($this->userManager->userExists($token)) {
1272
			throw new ShareNotFound();
1273
		}
1274
		$share = null;
1275
		try {
1276
			if($this->shareApiAllowLinks()) {
1277
				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_LINK);
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_LINK has been deprecated: 17.0.0 - use IShare::TYPE_LINK instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1277
				$provider = $this->factory->getProviderForType(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_LINK);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1278
				$share = $provider->getShareByToken($token);
1279
			}
1280
		} catch (ProviderException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1281
		} catch (ShareNotFound $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1282
		}
1283
1284
1285
		// If it is not a link share try to fetch a federated share by token
1286
		if ($share === null) {
1287
			try {
1288
				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE);
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_REMOTE has been deprecated: 17.0.0 - use IShare::TYPE_REMOTE instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1288
				$provider = $this->factory->getProviderForType(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_REMOTE);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1289
				$share = $provider->getShareByToken($token);
1290
			} catch (ProviderException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1291
			} catch (ShareNotFound $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1292
			}
1293
		}
1294
1295
		// If it is not a link share try to fetch a mail share by token
1296
		if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1296
		if ($share === null && $this->shareProviderExists(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL)) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1297
			try {
1298
				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_EMAIL);
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1298
				$provider = $this->factory->getProviderForType(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1299
				$share = $provider->getShareByToken($token);
1300
			} catch (ProviderException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1301
			} catch (ShareNotFound $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1302
			}
1303
		}
1304
1305
		if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_CIRCLE)) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_CIRCLE has been deprecated: 17.0.0 - use IShare::TYPE_CIRCLE instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1305
		if ($share === null && $this->shareProviderExists(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_CIRCLE)) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1306
			try {
1307
				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_CIRCLE);
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_CIRCLE has been deprecated: 17.0.0 - use IShare::TYPE_CIRCLE instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1307
				$provider = $this->factory->getProviderForType(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_CIRCLE);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1308
				$share = $provider->getShareByToken($token);
1309
			} catch (ProviderException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1310
			} catch (ShareNotFound $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1311
			}
1312
		}
1313
1314
		if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_ROOM)) {
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_ROOM has been deprecated: 17.0.0 - use IShare::TYPE_ROOM instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1314
		if ($share === null && $this->shareProviderExists(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_ROOM)) {

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1315
			try {
1316
				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_ROOM);
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_ROOM has been deprecated: 17.0.0 - use IShare::TYPE_ROOM instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1316
				$provider = $this->factory->getProviderForType(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_ROOM);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1317
				$share = $provider->getShareByToken($token);
1318
			} catch (ProviderException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1319
			} catch (ShareNotFound $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1320
			}
1321
		}
1322
1323
		if ($share === null) {
1324
			throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1325
		}
1326
1327
		$this->checkExpireDate($share);
1328
1329
		/*
1330
		 * Reduce the permissions for link shares if public upload is not enabled
1331
		 */
1332
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_LINK has been deprecated: 17.0.0 - use IShare::TYPE_LINK instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1332
		if ($share->getShareType() === /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_LINK &&

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1333
			!$this->shareApiLinkAllowPublicUpload()) {
1334
			$share->setPermissions($share->getPermissions() & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE));
1335
		}
1336
1337
		return $share;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $share returns the type OCP\Share\IShare which is incompatible with the documented return type OCP\Share.
Loading history...
1338
	}
1339
1340
	protected function checkExpireDate($share) {
1341
		if ($share->isExpired()) {
1342
			$this->deleteShare($share);
1343
			throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1344
		}
1345
1346
	}
1347
1348
	/**
1349
	 * Verify the password of a public share
1350
	 *
1351
	 * @param \OCP\Share\IShare $share
1352
	 * @param string $password
1353
	 * @return bool
1354
	 */
1355
	public function checkPassword(\OCP\Share\IShare $share, $password) {
1356
		$passwordProtected = $share->getShareType() !== \OCP\Share::SHARE_TYPE_LINK
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_LINK has been deprecated: 17.0.0 - use IShare::TYPE_LINK instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1356
		$passwordProtected = $share->getShareType() !== /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_LINK

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1357
			|| $share->getShareType() !== \OCP\Share::SHARE_TYPE_EMAIL;
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1357
			|| $share->getShareType() !== /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL;

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1358
		if (!$passwordProtected) {
1359
			//TODO maybe exception?
1360
			return false;
1361
		}
1362
1363
		if ($password === null || $share->getPassword() === null) {
0 ignored issues
show
introduced by
The condition $share->getPassword() === null is always false.
Loading history...
1364
			return false;
1365
		}
1366
1367
		$newHash = '';
1368
		if (!$this->hasher->verify($password, $share->getPassword(), $newHash)) {
1369
			return false;
1370
		}
1371
1372
		if (!empty($newHash)) {
1373
			$share->setPassword($newHash);
1374
			$provider = $this->factory->getProviderForType($share->getShareType());
1375
			$provider->update($share);
1376
		}
1377
1378
		return true;
1379
	}
1380
1381
	/**
1382
	 * @inheritdoc
1383
	 */
1384
	public function userDeleted($uid) {
1385
		$types = [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL];
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_USER has been deprecated: 17.0.0 - use IShare::TYPE_USER instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1385
		$types = [/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL];

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_REMOTE has been deprecated: 17.0.0 - use IShare::TYPE_REMOTE instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1385
		$types = [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL];

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1385
		$types = [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL];

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_LINK has been deprecated: 17.0.0 - use IShare::TYPE_LINK instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1385
		$types = [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL];

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_GROUP has been deprecated: 17.0.0 - use IShare::TYPE_GROUP instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1385
		$types = [\OCP\Share::SHARE_TYPE_USER, /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL];

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1386
1387
		foreach ($types as $type) {
1388
			try {
1389
				$provider = $this->factory->getProviderForType($type);
1390
			} catch (ProviderException $e) {
1391
				continue;
1392
			}
1393
			$provider->userDeleted($uid, $type);
1394
		}
1395
	}
1396
1397
	/**
1398
	 * @inheritdoc
1399
	 */
1400
	public function groupDeleted($gid) {
1401
		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_GROUP has been deprecated: 17.0.0 - use IShare::TYPE_GROUP instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1401
		$provider = $this->factory->getProviderForType(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_GROUP);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1402
		$provider->groupDeleted($gid);
1403
	}
1404
1405
	/**
1406
	 * @inheritdoc
1407
	 */
1408
	public function userDeletedFromGroup($uid, $gid) {
1409
		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_GROUP has been deprecated: 17.0.0 - use IShare::TYPE_GROUP instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1409
		$provider = $this->factory->getProviderForType(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_GROUP);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
1410
		$provider->userDeletedFromGroup($uid, $gid);
1411
	}
1412
1413
	/**
1414
	 * Get access list to a path. This means
1415
	 * all the users that can access a given path.
1416
	 *
1417
	 * Consider:
1418
	 * -root
1419
	 * |-folder1 (23)
1420
	 *  |-folder2 (32)
1421
	 *   |-fileA (42)
1422
	 *
1423
	 * fileA is shared with user1 and user1@server1
1424
	 * folder2 is shared with group2 (user4 is a member of group2)
1425
	 * folder1 is shared with user2 (renamed to "folder (1)") and user2@server2
1426
	 *
1427
	 * Then the access list to '/folder1/folder2/fileA' with $currentAccess is:
1428
	 * [
1429
	 *  users  => [
1430
	 *      'user1' => ['node_id' => 42, 'node_path' => '/fileA'],
1431
	 *      'user4' => ['node_id' => 32, 'node_path' => '/folder2'],
1432
	 *      'user2' => ['node_id' => 23, 'node_path' => '/folder (1)'],
1433
	 *  ],
1434
	 *  remote => [
1435
	 *      'user1@server1' => ['node_id' => 42, 'token' => 'SeCr3t'],
1436
	 *      'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
1437
	 *  ],
1438
	 *  public => bool
1439
	 *  mail => bool
1440
	 * ]
1441
	 *
1442
	 * The access list to '/folder1/folder2/fileA' **without** $currentAccess is:
1443
	 * [
1444
	 *  users  => ['user1', 'user2', 'user4'],
1445
	 *  remote => bool,
1446
	 *  public => bool
1447
	 *  mail => bool
1448
	 * ]
1449
	 *
1450
	 * This is required for encryption/activity
1451
	 *
1452
	 * @param \OCP\Files\Node $path
1453
	 * @param bool $recursive Should we check all parent folders as well
1454
	 * @param bool $currentAccess Ensure the recipient has access to the file (e.g. did not unshare it)
1455
	 * @return array
1456
	 */
1457
	public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false) {
1458
		$owner = $path->getOwner();
1459
1460
		if ($owner === null) {
1461
			return [];
1462
		}
1463
1464
		$owner = $owner->getUID();
1465
1466
		if ($currentAccess) {
1467
			$al = ['users' => [], 'remote' => [], 'public' => false];
1468
		} else {
1469
			$al = ['users' => [], 'remote' => false, 'public' => false];
1470
		}
1471
		if (!$this->userManager->userExists($owner)) {
1472
			return $al;
1473
		}
1474
1475
		//Get node for the owner and correct the owner in case of external storages
1476
		$userFolder = $this->rootFolder->getUserFolder($owner);
1477
		if ($path->getId() !== $userFolder->getId() && !$userFolder->isSubNode($path)) {
1478
			$nodes = $userFolder->getById($path->getId());
1479
			$path = array_shift($nodes);
1480
			if ($path->getOwner() === null) {
1481
				return [];
1482
			}
1483
			$owner = $path->getOwner()->getUID();
1484
		}
1485
1486
		$providers = $this->factory->getAllProviders();
1487
1488
		/** @var Node[] $nodes */
1489
		$nodes = [];
1490
1491
1492
		if ($currentAccess) {
1493
			$ownerPath = $path->getPath();
1494
			$ownerPath = explode('/', $ownerPath, 4);
1495
			if (count($ownerPath) < 4) {
1496
				$ownerPath = '';
1497
			} else {
1498
				$ownerPath = $ownerPath[3];
1499
			}
1500
			$al['users'][$owner] = [
1501
				'node_id' => $path->getId(),
1502
				'node_path' => '/' . $ownerPath,
1503
			];
1504
		} else {
1505
			$al['users'][] = $owner;
1506
		}
1507
1508
		// Collect all the shares
1509
		while ($path->getPath() !== $userFolder->getPath()) {
1510
			$nodes[] = $path;
1511
			if (!$recursive) {
1512
				break;
1513
			}
1514
			$path = $path->getParent();
1515
		}
1516
1517
		foreach ($providers as $provider) {
1518
			$tmp = $provider->getAccessList($nodes, $currentAccess);
1519
1520
			foreach ($tmp as $k => $v) {
1521
				if (isset($al[$k])) {
1522
					if (is_array($al[$k])) {
1523
						if ($currentAccess) {
1524
							$al[$k] += $v;
1525
						} else {
1526
							$al[$k] = array_merge($al[$k], $v);
1527
							$al[$k] = array_unique($al[$k]);
1528
							$al[$k] = array_values($al[$k]);
1529
						}
1530
					} else {
1531
						$al[$k] = $al[$k] || $v;
1532
					}
1533
				} else {
1534
					$al[$k] = $v;
1535
				}
1536
			}
1537
		}
1538
1539
		return $al;
1540
	}
1541
1542
	/**
1543
	 * Create a new share
1544
	 * @return \OCP\Share\IShare
1545
	 */
1546
	public function newShare() {
1547
		return new \OC\Share20\Share($this->rootFolder, $this->userManager);
1548
	}
1549
1550
	/**
1551
	 * Is the share API enabled
1552
	 *
1553
	 * @return bool
1554
	 */
1555
	public function shareApiEnabled() {
1556
		return $this->config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes';
1557
	}
1558
1559
	/**
1560
	 * Is public link sharing enabled
1561
	 *
1562
	 * @return bool
1563
	 */
1564
	public function shareApiAllowLinks() {
1565
		return $this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes';
1566
	}
1567
1568
	/**
1569
	 * Is password on public link requires
1570
	 *
1571
	 * @return bool
1572
	 */
1573
	public function shareApiLinkEnforcePassword() {
1574
		return $this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes';
1575
	}
1576
1577
	/**
1578
	 * Is default expire date enabled
1579
	 *
1580
	 * @return bool
1581
	 */
1582
	public function shareApiLinkDefaultExpireDate() {
1583
		return $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
1584
	}
1585
1586
	/**
1587
	 * Is default expire date enforced
1588
	 *`
1589
	 * @return bool
1590
	 */
1591
	public function shareApiLinkDefaultExpireDateEnforced() {
1592
		return $this->shareApiLinkDefaultExpireDate() &&
1593
			$this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
1594
	}
1595
1596
	/**
1597
	 * Number of default expire days
1598
	 *shareApiLinkAllowPublicUpload
1599
	 * @return int
1600
	 */
1601
	public function shareApiLinkDefaultExpireDays() {
1602
		return (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1603
	}
1604
1605
	/**
1606
	 * Allow public upload on link shares
1607
	 *
1608
	 * @return bool
1609
	 */
1610
	public function shareApiLinkAllowPublicUpload() {
1611
		return $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes';
1612
	}
1613
1614
	/**
1615
	 * check if user can only share with group members
1616
	 * @return bool
1617
	 */
1618
	public function shareWithGroupMembersOnly() {
1619
		return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
1620
	}
1621
1622
	/**
1623
	 * Check if users can share with groups
1624
	 * @return bool
1625
	 */
1626
	public function allowGroupSharing() {
1627
		return $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes';
1628
	}
1629
1630
	/**
1631
	 * Copied from \OC_Util::isSharingDisabledForUser
1632
	 *
1633
	 * TODO: Deprecate fuction from OC_Util
1634
	 *
1635
	 * @param string $userId
1636
	 * @return bool
1637
	 */
1638
	public function sharingDisabledForUser($userId) {
1639
		if ($userId === null) {
0 ignored issues
show
introduced by
The condition $userId === null is always false.
Loading history...
1640
			return false;
1641
		}
1642
1643
		if (isset($this->sharingDisabledForUsersCache[$userId])) {
1644
			return $this->sharingDisabledForUsersCache[$userId];
1645
		}
1646
1647
		if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
1648
			$groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
1649
			$excludedGroups = json_decode($groupsList);
1650
			if (is_null($excludedGroups)) {
1651
				$excludedGroups = explode(',', $groupsList);
1652
				$newValue = json_encode($excludedGroups);
1653
				$this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
1654
			}
1655
			$user = $this->userManager->get($userId);
1656
			$usersGroups = $this->groupManager->getUserGroupIds($user);
1657
			if (!empty($usersGroups)) {
1658
				$remainingGroups = array_diff($usersGroups, $excludedGroups);
1659
				// if the user is only in groups which are disabled for sharing then
1660
				// sharing is also disabled for the user
1661
				if (empty($remainingGroups)) {
1662
					$this->sharingDisabledForUsersCache[$userId] = true;
1663
					return true;
1664
				}
1665
			}
1666
		}
1667
1668
		$this->sharingDisabledForUsersCache[$userId] = false;
1669
		return false;
1670
	}
1671
1672
	/**
1673
	 * @inheritdoc
1674
	 */
1675
	public function outgoingServer2ServerSharesAllowed() {
1676
		return $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
1677
	}
1678
1679
	/**
1680
	 * @inheritdoc
1681
	 */
1682
	public function outgoingServer2ServerGroupSharesAllowed() {
1683
		return $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no') === 'yes';
1684
	}
1685
1686
	/**
1687
	 * @inheritdoc
1688
	 */
1689
	public function shareProviderExists($shareType) {
1690
		try {
1691
			$this->factory->getProviderForType($shareType);
1692
		} catch (ProviderException $e) {
1693
			return false;
1694
		}
1695
1696
		return true;
1697
	}
1698
1699
	public function getAllShares(): iterable {
1700
		$providers = $this->factory->getAllProviders();
1701
1702
		foreach ($providers as $provider) {
1703
			yield from $provider->getAllShares();
1704
		}
1705
	}
1706
}
1707