Passed
Push — master ( 6b97f6...a6ae80 )
by Blizzz
13:11 queued 11s
created

DefaultShareProvider::create()   C

Complexity

Conditions 12
Paths 73

Size

Total Lines 100
Code Lines 53

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 53
c 0
b 0
f 0
dl 0
loc 100
rs 6.9666
cc 12
nc 73
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Andrius <[email protected]>
6
 * @author Bjoern Schiessle <[email protected]>
7
 * @author Björn Schießle <[email protected]>
8
 * @author Jan-Philipp Litza <[email protected]>
9
 * @author Joas Schilling <[email protected]>
10
 * @author phisch <[email protected]>
11
 * @author Robin Appelman <[email protected]>
12
 * @author Roeland Jago Douma <[email protected]>
13
 * @author Vincent Petry <[email protected]>
14
 *
15
 * @license AGPL-3.0
16
 *
17
 * This code is free software: you can redistribute it and/or modify
18
 * it under the terms of the GNU Affero General Public License, version 3,
19
 * as published by the Free Software Foundation.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License, version 3,
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
28
 *
29
 */
30
31
namespace OC\Share20;
32
33
use OC\Files\Cache\Cache;
34
use OC\Share20\Exception\BackendError;
35
use OC\Share20\Exception\InvalidShare;
36
use OC\Share20\Exception\ProviderException;
37
use OCP\DB\QueryBuilder\IQueryBuilder;
38
use OCP\Defaults;
39
use OCP\Files\Folder;
40
use OCP\Files\IRootFolder;
41
use OCP\Files\Node;
42
use OCP\IDBConnection;
43
use OCP\IGroup;
44
use OCP\IGroupManager;
45
use OCP\IL10N;
46
use OCP\IURLGenerator;
47
use OCP\IUser;
48
use OCP\IUserManager;
49
use OCP\Mail\IMailer;
50
use OCP\Share\Exceptions\ShareNotFound;
51
use OCP\Share\IShare;
52
use OCP\Share\IShareHelper;
53
use OCP\Share\IShareProvider;
54
55
/**
56
 * Class DefaultShareProvider
57
 *
58
 * @package OC\Share20
59
 */
60
class DefaultShareProvider implements IShareProvider {
61
62
	// Special share type for user modified group shares
63
	const SHARE_TYPE_USERGROUP = 2;
64
65
	/** @var IDBConnection */
66
	private $dbConn;
67
68
	/** @var IUserManager */
69
	private $userManager;
70
71
	/** @var IGroupManager */
72
	private $groupManager;
73
74
	/** @var IRootFolder */
75
	private $rootFolder;
76
77
	/** @var IMailer */
78
	private $mailer;
79
80
	/** @var Defaults */
81
	private $defaults;
82
83
	/** @var IL10N */
84
	private $l;
85
86
	/** @var IURLGenerator */
87
	private $urlGenerator;
88
89
	/**
90
	 * DefaultShareProvider constructor.
91
	 *
92
	 * @param IDBConnection $connection
93
	 * @param IUserManager $userManager
94
	 * @param IGroupManager $groupManager
95
	 * @param IRootFolder $rootFolder
96
	 * @param IMailer $mailer ;
97
	 * @param Defaults $defaults
98
	 * @param IL10N $l
99
	 * @param IURLGenerator $urlGenerator
100
	 */
101
	public function __construct(
102
			IDBConnection $connection,
103
			IUserManager $userManager,
104
			IGroupManager $groupManager,
105
			IRootFolder $rootFolder,
106
			IMailer $mailer,
107
			Defaults $defaults,
108
			IL10N $l,
109
			IURLGenerator $urlGenerator) {
110
		$this->dbConn = $connection;
111
		$this->userManager = $userManager;
112
		$this->groupManager = $groupManager;
113
		$this->rootFolder = $rootFolder;
114
		$this->mailer = $mailer;
115
		$this->defaults = $defaults;
116
		$this->l = $l;
117
		$this->urlGenerator = $urlGenerator;
118
	}
119
120
	/**
121
	 * Return the identifier of this provider.
122
	 *
123
	 * @return string Containing only [a-zA-Z0-9]
124
	 */
125
	public function identifier() {
126
		return 'ocinternal';
127
	}
128
129
	/**
130
	 * Share a path
131
	 *
132
	 * @param \OCP\Share\IShare $share
133
	 * @return \OCP\Share\IShare The share object
134
	 * @throws ShareNotFound
135
	 * @throws \Exception
136
	 */
137
	public function create(\OCP\Share\IShare $share) {
138
		$qb = $this->dbConn->getQueryBuilder();
139
140
		$qb->insert('share');
141
		$qb->setValue('share_type', $qb->createNamedParameter($share->getShareType()));
142
143
		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

143
		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...
144
			//Set the UID of the user we share with
145
			$qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
146
			$qb->setValue('accepted', $qb->createNamedParameter(IShare::STATUS_PENDING));
147
148
			//If an expiration date is set store it
149
			if ($share->getExpirationDate() !== null) {
150
				$qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
151
			}
152
		} 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

152
		} 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...
153
			//Set the GID of the group we share with
154
			$qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
155
156
			//If an expiration date is set store it
157
			if ($share->getExpirationDate() !== null) {
158
				$qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
159
			}
160
		} 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

160
		} 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...
161
			//set label for public link
162
			$qb->setValue('label', $qb->createNamedParameter($share->getLabel()));
163
			//Set the token of the share
164
			$qb->setValue('token', $qb->createNamedParameter($share->getToken()));
165
166
			//If a password is set store it
167
			if ($share->getPassword() !== null) {
0 ignored issues
show
introduced by
The condition $share->getPassword() !== null is always true.
Loading history...
168
				$qb->setValue('password', $qb->createNamedParameter($share->getPassword()));
169
			}
170
171
			$qb->setValue('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL));
172
173
			//If an expiration date is set store it
174
			if ($share->getExpirationDate() !== null) {
175
				$qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
176
			}
177
178
			if (method_exists($share, 'getParent')) {
179
				$qb->setValue('parent', $qb->createNamedParameter($share->getParent()));
180
			}
181
		} else {
182
			throw new \Exception('invalid share type!');
183
		}
184
185
		// Set what is shares
186
		$qb->setValue('item_type', $qb->createParameter('itemType'));
187
		if ($share->getNode() instanceof \OCP\Files\File) {
188
			$qb->setParameter('itemType', 'file');
189
		} else {
190
			$qb->setParameter('itemType', 'folder');
191
		}
192
193
		// Set the file id
194
		$qb->setValue('item_source', $qb->createNamedParameter($share->getNode()->getId()));
195
		$qb->setValue('file_source', $qb->createNamedParameter($share->getNode()->getId()));
196
197
		// set the permissions
198
		$qb->setValue('permissions', $qb->createNamedParameter($share->getPermissions()));
199
200
		// Set who created this share
201
		$qb->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()));
202
203
		// Set who is the owner of this file/folder (and this the owner of the share)
204
		$qb->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner()));
205
206
		// Set the file target
207
		$qb->setValue('file_target', $qb->createNamedParameter($share->getTarget()));
208
209
		// Set the time this share was created
210
		$qb->setValue('stime', $qb->createNamedParameter(time()));
211
212
		// insert the data and fetch the id of the share
213
		$this->dbConn->beginTransaction();
214
		$qb->execute();
215
		$id = $this->dbConn->lastInsertId('*PREFIX*share');
216
217
		// Now fetch the inserted share and create a complete share object
218
		$qb = $this->dbConn->getQueryBuilder();
219
		$qb->select('*')
220
			->from('share')
221
			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
222
223
		$cursor = $qb->execute();
224
		$data = $cursor->fetch();
225
		$this->dbConn->commit();
226
		$cursor->closeCursor();
227
228
		if ($data === false) {
229
			throw new ShareNotFound();
230
		}
231
232
		$mailSendValue = $share->getMailSend();
233
		$data['mail_send'] = ($mailSendValue === null) ? true : $mailSendValue;
0 ignored issues
show
introduced by
The condition $mailSendValue === null is always false.
Loading history...
234
235
		$share = $this->createShare($data);
236
		return $share;
237
	}
238
239
	/**
240
	 * Update a share
241
	 *
242
	 * @param \OCP\Share\IShare $share
243
	 * @return \OCP\Share\IShare The share object
244
	 * @throws ShareNotFound
245
	 * @throws \OCP\Files\InvalidPathException
246
	 * @throws \OCP\Files\NotFoundException
247
	 */
248
	public function update(\OCP\Share\IShare $share) {
249
250
		$originalShare = $this->getShareById($share->getId());
251
252
		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

252
		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...
253
			/*
254
			 * We allow updating the recipient on user shares.
255
			 */
256
			$qb = $this->dbConn->getQueryBuilder();
257
			$qb->update('share')
258
				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
259
				->set('share_with', $qb->createNamedParameter($share->getSharedWith()))
260
				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
261
				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
262
				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
263
				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
264
				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
265
				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
266
				->set('note', $qb->createNamedParameter($share->getNote()))
267
				->set('accepted', $qb->createNamedParameter($share->getStatus()))
268
				->execute();
269
		} 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

269
		} 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...
270
			$qb = $this->dbConn->getQueryBuilder();
271
			$qb->update('share')
272
				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
273
				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
274
				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
275
				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
276
				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
277
				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
278
				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
279
				->set('note', $qb->createNamedParameter($share->getNote()))
280
				->execute();
281
282
			/*
283
			 * Update all user defined group shares
284
			 */
285
			$qb = $this->dbConn->getQueryBuilder();
286
			$qb->update('share')
287
				->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
288
				->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
289
				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
290
				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
291
				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
292
				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
293
				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
294
				->set('note', $qb->createNamedParameter($share->getNote()))
295
				->execute();
296
297
			/*
298
			 * Now update the permissions for all children that have not set it to 0
299
			 */
300
			$qb = $this->dbConn->getQueryBuilder();
301
			$qb->update('share')
302
				->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
303
				->andWhere($qb->expr()->neq('permissions', $qb->createNamedParameter(0)))
304
				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
305
				->execute();
306
307
		} 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

307
		} 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...
308
			$qb = $this->dbConn->getQueryBuilder();
309
			$qb->update('share')
310
				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
311
				->set('password', $qb->createNamedParameter($share->getPassword()))
312
				->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
313
				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
314
				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
315
				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
316
				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
317
				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
318
				->set('token', $qb->createNamedParameter($share->getToken()))
319
				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
320
				->set('note', $qb->createNamedParameter($share->getNote()))
321
				->set('label', $qb->createNamedParameter($share->getLabel()))
322
				->set('hide_download', $qb->createNamedParameter($share->getHideDownload() ? 1 : 0), IQueryBuilder::PARAM_INT)
0 ignored issues
show
Unused Code introduced by
The call to OCP\DB\QueryBuilder\IQueryBuilder::set() has too many arguments starting with OCP\DB\QueryBuilder\IQueryBuilder::PARAM_INT. ( Ignorable by Annotation )

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

322
				->/** @scrutinizer ignore-call */ set('hide_download', $qb->createNamedParameter($share->getHideDownload() ? 1 : 0), IQueryBuilder::PARAM_INT)

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...
323
				->execute();
324
		}
325
326
		if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
327
			$this->propagateNote($share);
328
		}
329
330
331
		return $share;
332
	}
333
334
	/**
335
	 * Accept a share.
336
	 *
337
	 * @param IShare $share
338
	 * @param string $recipient
339
	 * @return IShare The share object
340
	 * @since 9.0.0
341
	 */
342
	public function acceptShare(IShare $share, string $recipient): IShare {
343
		if ($share->getShareType() === IShare::TYPE_GROUP) {
344
			$group = $this->groupManager->get($share->getSharedWith());
345
			$user = $this->userManager->get($recipient);
346
347
			if (is_null($group)) {
348
				throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
349
			}
350
351
			if (!$group->inGroup($user)) {
352
				throw new ProviderException('Recipient not in receiving group');
353
			}
354
355
			// Try to fetch user specific share
356
			$qb = $this->dbConn->getQueryBuilder();
357
			$stmt = $qb->select('*')
358
				->from('share')
359
				->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
360
				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
361
				->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
362
				->andWhere($qb->expr()->orX(
363
					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
364
					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
365
				))
366
				->execute();
367
368
			$data = $stmt->fetch();
369
			$stmt->closeCursor();
370
371
			/*
372
			 * Check if there already is a user specific group share.
373
			 * If there is update it (if required).
374
			 */
375
			if ($data === false) {
376
				$id = $this->createUserSpecificGroupShare($share, $recipient);
377
			} else {
378
				$id = $data['id'];
379
			}
380
381
		} else if ($share->getShareType() === IShare::TYPE_USER) {
382
			if ($share->getSharedWith() !== $recipient) {
383
				throw new ProviderException('Recipient does not match');
384
			}
385
386
			$id = $share->getId();
387
		} else {
388
			throw new ProviderException('Invalid shareType');
389
		}
390
391
		$qb = $this->dbConn->getQueryBuilder();
392
		$qb->update('share')
393
			->set('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED))
394
			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
395
			->execute();
396
397
		return $share;
398
	}
399
400
	/**
401
	 * Get all children of this share
402
	 * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
403
	 *
404
	 * @param \OCP\Share\IShare $parent
405
	 * @return \OCP\Share\IShare[]
406
	 */
407
	public function getChildren(\OCP\Share\IShare $parent) {
408
		$children = [];
409
410
		$qb = $this->dbConn->getQueryBuilder();
411
		$qb->select('*')
412
			->from('share')
413
			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
414
			->andWhere(
415
				$qb->expr()->in(
416
					'share_type',
417
					$qb->createNamedParameter([
418
						\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

418
						/** @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...
419
						\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

419
						/** @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...
420
						\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

420
						/** @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...
421
					], IQueryBuilder::PARAM_INT_ARRAY)
422
				)
423
			)
424
			->andWhere($qb->expr()->orX(
425
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
426
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
427
			))
428
			->orderBy('id');
429
430
		$cursor = $qb->execute();
431
		while($data = $cursor->fetch()) {
432
			$children[] = $this->createShare($data);
433
		}
434
		$cursor->closeCursor();
435
436
		return $children;
437
	}
438
439
	/**
440
	 * Delete a share
441
	 *
442
	 * @param \OCP\Share\IShare $share
443
	 */
444
	public function delete(\OCP\Share\IShare $share) {
445
		$qb = $this->dbConn->getQueryBuilder();
446
		$qb->delete('share')
447
			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())));
448
449
		/*
450
		 * If the share is a group share delete all possible
451
		 * user defined groups shares.
452
		 */
453
		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

453
		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...
454
			$qb->orWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())));
455
		}
456
457
		$qb->execute();
458
	}
459
460
	/**
461
	 * Unshare a share from the recipient. If this is a group share
462
	 * this means we need a special entry in the share db.
463
	 *
464
	 * @param IShare $share
465
	 * @param string $recipient UserId of recipient
466
	 * @throws BackendError
467
	 * @throws ProviderException
468
	 */
469
	public function deleteFromSelf(IShare $share, $recipient) {
470
		if ($share->getShareType() === IShare::TYPE_GROUP) {
471
472
			$group = $this->groupManager->get($share->getSharedWith());
473
			$user = $this->userManager->get($recipient);
474
475
			if (is_null($group)) {
476
				throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
477
			}
478
479
			if (!$group->inGroup($user)) {
480
				throw new ProviderException('Recipient not in receiving group');
481
			}
482
483
			// Try to fetch user specific share
484
			$qb = $this->dbConn->getQueryBuilder();
485
			$stmt = $qb->select('*')
486
				->from('share')
487
				->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
488
				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
489
				->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
490
				->andWhere($qb->expr()->orX(
491
					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
492
					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
493
				))
494
				->execute();
495
496
			$data = $stmt->fetch();
497
498
			/*
499
			 * Check if there already is a user specific group share.
500
			 * If there is update it (if required).
501
			 */
502
			if ($data === false) {
503
				$id = $this->createUserSpecificGroupShare($share, $recipient);
504
				$permissions = $share->getPermissions();
505
			} else {
506
				$permissions = $data['permissions'];
507
				$id = $data['id'];
508
			}
509
510
			if ($permissions !== 0) {
511
				// Update existing usergroup share
512
				$qb = $this->dbConn->getQueryBuilder();
513
				$qb->update('share')
514
					->set('permissions', $qb->createNamedParameter(0))
515
					->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
516
					->execute();
517
			}
518
519
		} else if ($share->getShareType() === IShare::TYPE_USER) {
520
521
			if ($share->getSharedWith() !== $recipient) {
522
				throw new ProviderException('Recipient does not match');
523
			}
524
525
			// We can just delete user and link shares
526
			$this->delete($share);
527
		} else {
528
			throw new ProviderException('Invalid shareType');
529
		}
530
	}
531
532
	protected function createUserSpecificGroupShare(IShare $share, string $recipient): int {
533
		$type = $share->getNodeType();
534
535
		$qb = $this->dbConn->getQueryBuilder();
536
		$qb->insert('share')
537
			->values([
538
				'share_type' => $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP),
539
				'share_with' => $qb->createNamedParameter($recipient),
540
				'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
541
				'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
542
				'parent' => $qb->createNamedParameter($share->getId()),
543
				'item_type' => $qb->createNamedParameter($type),
544
				'item_source' => $qb->createNamedParameter($share->getNodeId()),
545
				'file_source' => $qb->createNamedParameter($share->getNodeId()),
546
				'file_target' => $qb->createNamedParameter($share->getTarget()),
547
				'permissions' => $qb->createNamedParameter($share->getPermissions()),
548
				'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
549
			])->execute();
550
551
		return $qb->getLastInsertId();
552
	}
553
554
	/**
555
	 * @inheritdoc
556
	 *
557
	 * For now this only works for group shares
558
	 * If this gets implemented for normal shares we have to extend it
559
	 */
560
	public function restore(IShare $share, string $recipient): IShare {
561
		$qb = $this->dbConn->getQueryBuilder();
562
		$qb->select('permissions')
563
			->from('share')
564
			->where(
565
				$qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))
566
			);
567
		$cursor = $qb->execute();
568
		$data = $cursor->fetch();
569
		$cursor->closeCursor();
570
571
		$originalPermission = $data['permissions'];
572
573
		$qb = $this->dbConn->getQueryBuilder();
574
		$qb->update('share')
575
			->set('permissions', $qb->createNamedParameter($originalPermission))
576
			->where(
577
				$qb->expr()->eq('parent', $qb->createNamedParameter($share->getParent()))
0 ignored issues
show
Bug introduced by
The method getParent() does not exist on OCP\Share\IShare. Since it exists in all sub-types, consider adding an abstract or default implementation to OCP\Share\IShare. ( Ignorable by Annotation )

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

577
				$qb->expr()->eq('parent', $qb->createNamedParameter($share->/** @scrutinizer ignore-call */ getParent()))
Loading history...
578
			)->andWhere(
579
				$qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP))
580
			)->andWhere(
581
				$qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))
582
			);
583
584
		$qb->execute();
585
586
		return $this->getShareById($share->getId(), $recipient);
587
	}
588
589
	/**
590
	 * @inheritdoc
591
	 */
592
	public function move(\OCP\Share\IShare $share, $recipient) {
593
		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

593
		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...
594
			// Just update the target
595
			$qb = $this->dbConn->getQueryBuilder();
596
			$qb->update('share')
597
				->set('file_target', $qb->createNamedParameter($share->getTarget()))
598
				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
599
				->execute();
600
601
		} 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

601
		} 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...
602
603
			// Check if there is a usergroup share
604
			$qb = $this->dbConn->getQueryBuilder();
605
			$stmt = $qb->select('id')
606
				->from('share')
607
				->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
608
				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
609
				->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
610
				->andWhere($qb->expr()->orX(
611
					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
612
					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
613
				))
614
				->setMaxResults(1)
615
				->execute();
616
617
			$data = $stmt->fetch();
618
			$stmt->closeCursor();
619
620
			if ($data === false) {
621
				// No usergroup share yet. Create one.
622
				$qb = $this->dbConn->getQueryBuilder();
623
				$qb->insert('share')
624
					->values([
625
						'share_type' => $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP),
626
						'share_with' => $qb->createNamedParameter($recipient),
627
						'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
628
						'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
629
						'parent' => $qb->createNamedParameter($share->getId()),
630
						'item_type' => $qb->createNamedParameter($share->getNodeType()),
631
						'item_source' => $qb->createNamedParameter($share->getNodeId()),
632
						'file_source' => $qb->createNamedParameter($share->getNodeId()),
633
						'file_target' => $qb->createNamedParameter($share->getTarget()),
634
						'permissions' => $qb->createNamedParameter($share->getPermissions()),
635
						'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
636
					])->execute();
637
			} else {
638
				// Already a usergroup share. Update it.
639
				$qb = $this->dbConn->getQueryBuilder();
640
				$qb->update('share')
641
					->set('file_target', $qb->createNamedParameter($share->getTarget()))
642
					->where($qb->expr()->eq('id', $qb->createNamedParameter($data['id'])))
643
					->execute();
644
			}
645
		}
646
647
		return $share;
648
	}
649
650
	public function getSharesInFolder($userId, Folder $node, $reshares) {
651
		$qb = $this->dbConn->getQueryBuilder();
652
		$qb->select('*')
653
			->from('share', 's')
654
			->andWhere($qb->expr()->orX(
655
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
656
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
657
			));
658
659
		$qb->andWhere($qb->expr()->orX(
660
			$qb->expr()->eq('share_type', $qb->createNamedParameter(\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

660
			$qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
661
			$qb->expr()->eq('share_type', $qb->createNamedParameter(\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

661
			$qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
662
			$qb->expr()->eq('share_type', $qb->createNamedParameter(\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

662
			$qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
663
		));
664
665
		/**
666
		 * Reshares for this user are shares where they are the owner.
667
		 */
668
		if ($reshares === false) {
669
			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
670
		} else {
671
			$qb->andWhere(
672
				$qb->expr()->orX(
673
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
674
					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
675
				)
676
			);
677
		}
678
679
		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
680
		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
681
682
		$qb->orderBy('id');
683
684
		$cursor = $qb->execute();
685
		$shares = [];
686
		while ($data = $cursor->fetch()) {
687
			$shares[$data['fileid']][] = $this->createShare($data);
688
		}
689
		$cursor->closeCursor();
690
691
		return $shares;
692
	}
693
694
	/**
695
	 * @inheritdoc
696
	 */
697
	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
698
		$qb = $this->dbConn->getQueryBuilder();
699
		$qb->select('*')
700
			->from('share')
701
			->andWhere($qb->expr()->orX(
702
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
703
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
704
			));
705
706
		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
707
708
		/**
709
		 * Reshares for this user are shares where they are the owner.
710
		 */
711
		if ($reshares === false) {
712
			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
713
		} else {
714
			if ($node === null) {
715
				$qb->andWhere(
716
					$qb->expr()->orX(
717
						$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
718
						$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
719
					)
720
				);
721
			}
722
		}
723
724
		if ($node !== null) {
725
			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
726
		}
727
728
		if ($limit !== -1) {
729
			$qb->setMaxResults($limit);
730
		}
731
732
		$qb->setFirstResult($offset);
733
		$qb->orderBy('id');
734
735
		$cursor = $qb->execute();
736
		$shares = [];
737
		while($data = $cursor->fetch()) {
738
			$shares[] = $this->createShare($data);
739
		}
740
		$cursor->closeCursor();
741
742
		return $shares;
743
	}
744
745
	/**
746
	 * @inheritdoc
747
	 */
748
	public function getShareById($id, $recipientId = null) {
749
		$qb = $this->dbConn->getQueryBuilder();
750
751
		$qb->select('*')
752
			->from('share')
753
			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
754
			->andWhere(
755
				$qb->expr()->in(
756
					'share_type',
757
					$qb->createNamedParameter([
758
						\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

758
						/** @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...
759
						\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

759
						/** @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...
760
						\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

760
						/** @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...
761
					], IQueryBuilder::PARAM_INT_ARRAY)
762
				)
763
			)
764
			->andWhere($qb->expr()->orX(
765
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
766
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
767
			));
768
769
		$cursor = $qb->execute();
770
		$data = $cursor->fetch();
771
		$cursor->closeCursor();
772
773
		if ($data === false) {
774
			throw new ShareNotFound();
775
		}
776
777
		try {
778
			$share = $this->createShare($data);
779
		} catch (InvalidShare $e) {
780
			throw new ShareNotFound();
781
		}
782
783
		// If the recipient is set for a group share resolve to that user
784
		if ($recipientId !== null && $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

784
		if ($recipientId !== null && $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...
785
			$share = $this->resolveGroupShares([$share], $recipientId)[0];
786
		}
787
788
		return $share;
789
	}
790
791
	/**
792
	 * Get shares for a given path
793
	 *
794
	 * @param \OCP\Files\Node $path
795
	 * @return \OCP\Share\IShare[]
796
	 */
797
	public function getSharesByPath(Node $path) {
798
		$qb = $this->dbConn->getQueryBuilder();
799
800
		$cursor = $qb->select('*')
801
			->from('share')
802
			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
803
			->andWhere(
804
				$qb->expr()->orX(
805
					$qb->expr()->eq('share_type', $qb->createNamedParameter(\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

805
					$qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
806
					$qb->expr()->eq('share_type', $qb->createNamedParameter(\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

806
					$qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
807
				)
808
			)
809
			->andWhere($qb->expr()->orX(
810
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
811
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
812
			))
813
			->execute();
814
815
		$shares = [];
816
		while($data = $cursor->fetch()) {
817
			$shares[] = $this->createShare($data);
818
		}
819
		$cursor->closeCursor();
820
821
		return $shares;
822
	}
823
824
	/**
825
	 * Returns whether the given database result can be interpreted as
826
	 * a share with accessible file (not trashed, not deleted)
827
	 */
828
	private function isAccessibleResult($data) {
829
		// exclude shares leading to deleted file entries
830
		if ($data['fileid'] === null) {
831
			return false;
832
		}
833
834
		// exclude shares leading to trashbin on home storages
835
		$pathSections = explode('/', $data['path'], 2);
836
		// FIXME: would not detect rare md5'd home storage case properly
837
		if ($pathSections[0] !== 'files'
838
		    	&& in_array(explode(':', $data['storage_string_id'], 2)[0], array('home', 'object'))) {
839
			return false;
840
		}
841
		return true;
842
	}
843
844
	/**
845
	 * @inheritdoc
846
	 */
847
	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
848
		/** @var Share[] $shares */
849
		$shares = [];
850
851
		if ($shareType === \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 ($shareType === /** @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
			//Get shares directly with this user
853
			$qb = $this->dbConn->getQueryBuilder();
854
			$qb->select('s.*',
855
				'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
856
				'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
857
				'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
858
			)
859
				->selectAlias('st.id', 'storage_string_id')
860
				->from('share', 's')
861
				->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
862
				->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'));
863
864
			// Order by id
865
			$qb->orderBy('s.id');
866
867
			// Set limit and offset
868
			if ($limit !== -1) {
869
				$qb->setMaxResults($limit);
870
			}
871
			$qb->setFirstResult($offset);
872
873
			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\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

873
			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
874
				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
875
				->andWhere($qb->expr()->orX(
876
					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
877
					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
878
				));
879
880
			// Filter by node if provided
881
			if ($node !== null) {
882
				$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
883
			}
884
885
			$cursor = $qb->execute();
886
887
			while($data = $cursor->fetch()) {
888
				if ($this->isAccessibleResult($data)) {
889
					$shares[] = $this->createShare($data);
890
				}
891
			}
892
			$cursor->closeCursor();
893
894
		} else if ($shareType === \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

894
		} else if ($shareType === /** @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...
895
			$user = $this->userManager->get($userId);
896
			$allGroups = $this->groupManager->getUserGroups($user);
897
898
			/** @var Share[] $shares2 */
899
			$shares2 = [];
900
901
			$start = 0;
902
			while(true) {
903
				$groups = array_slice($allGroups, $start, 100);
904
				$start += 100;
905
906
				if ($groups === []) {
907
					break;
908
				}
909
910
				$qb = $this->dbConn->getQueryBuilder();
911
				$qb->select('s.*',
912
					'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
913
					'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
914
					'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
915
				)
916
					->selectAlias('st.id', 'storage_string_id')
917
					->from('share', 's')
918
					->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
919
					->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'))
920
					->orderBy('s.id')
921
					->setFirstResult(0);
922
923
				if ($limit !== -1) {
924
					$qb->setMaxResults($limit - count($shares));
925
				}
926
927
				// Filter by node if provided
928
				if ($node !== null) {
929
					$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
930
				}
931
932
933
				$groups = array_filter($groups, function($group) { return $group instanceof IGroup; });
934
				$groups = array_map(function(IGroup $group) { return $group->getGID(); }, $groups);
935
936
				$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\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

936
				$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
937
					->andWhere($qb->expr()->in('share_with', $qb->createNamedParameter(
938
						$groups,
939
						IQueryBuilder::PARAM_STR_ARRAY
940
					)))
941
					->andWhere($qb->expr()->orX(
942
						$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
943
						$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
944
					));
945
946
				$cursor = $qb->execute();
947
				while($data = $cursor->fetch()) {
948
					if ($offset > 0) {
949
						$offset--;
950
						continue;
951
					}
952
953
					if ($this->isAccessibleResult($data)) {
954
						$shares2[] = $this->createShare($data);
955
					}
956
				}
957
				$cursor->closeCursor();
958
			}
959
960
			/*
961
 			 * Resolve all group shares to user specific shares
962
 			 */
963
			$shares = $this->resolveGroupShares($shares2, $userId);
964
		} else {
965
			throw new BackendError('Invalid backend');
966
		}
967
968
969
		return $shares;
970
	}
971
972
	/**
973
	 * Get a share by token
974
	 *
975
	 * @param string $token
976
	 * @return \OCP\Share\IShare
977
	 * @throws ShareNotFound
978
	 */
979
	public function getShareByToken($token) {
980
		$qb = $this->dbConn->getQueryBuilder();
981
982
		$cursor = $qb->select('*')
983
			->from('share')
984
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\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

984
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
985
			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
986
			->andWhere($qb->expr()->orX(
987
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
988
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
989
			))
990
			->execute();
991
992
		$data = $cursor->fetch();
993
994
		if ($data === false) {
995
			throw new ShareNotFound();
996
		}
997
998
		try {
999
			$share = $this->createShare($data);
1000
		} catch (InvalidShare $e) {
1001
			throw new ShareNotFound();
1002
		}
1003
1004
		return $share;
1005
	}
1006
1007
	/**
1008
	 * Create a share object from an database row
1009
	 *
1010
	 * @param mixed[] $data
1011
	 * @return \OCP\Share\IShare
1012
	 * @throws InvalidShare
1013
	 */
1014
	private function createShare($data) {
1015
		$share = new Share($this->rootFolder, $this->userManager);
1016
		$share->setId((int)$data['id'])
1017
			->setShareType((int)$data['share_type'])
1018
			->setPermissions((int)$data['permissions'])
1019
			->setTarget($data['file_target'])
1020
			->setNote($data['note'])
1021
			->setMailSend((bool)$data['mail_send'])
1022
			->setStatus((int)$data['accepted'])
1023
			->setLabel($data['label']);
1024
1025
		$shareTime = new \DateTime();
1026
		$shareTime->setTimestamp((int)$data['stime']);
1027
		$share->setShareTime($shareTime);
1028
1029
		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

1029
		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...
1030
			$share->setSharedWith($data['share_with']);
1031
			$user = $this->userManager->get($data['share_with']);
1032
			if ($user !== null) {
1033
				$share->setSharedWithDisplayName($user->getDisplayName());
1034
			}
1035
		} 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

1035
		} 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...
1036
			$share->setSharedWith($data['share_with']);
1037
		} 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

1037
		} 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...
1038
			$share->setPassword($data['password']);
1039
			$share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1040
			$share->setToken($data['token']);
1041
		}
1042
1043
		$share->setSharedBy($data['uid_initiator']);
1044
		$share->setShareOwner($data['uid_owner']);
1045
1046
		$share->setNodeId((int)$data['file_source']);
1047
		$share->setNodeType($data['item_type']);
1048
1049
		if ($data['expiration'] !== null) {
1050
			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
1051
			$share->setExpirationDate($expiration);
1052
		}
1053
1054
		if (isset($data['f_permissions'])) {
1055
			$entryData = $data;
1056
			$entryData['permissions'] = $entryData['f_permissions'];
1057
			$entryData['parent'] = $entryData['f_parent'];
1058
			$share->setNodeCacheEntry(Cache::cacheEntryFromData($entryData,
1059
				\OC::$server->getMimeTypeLoader()));
1060
		}
1061
1062
		$share->setProviderId($this->identifier());
1063
		$share->setHideDownload((int)$data['hide_download'] === 1);
1064
1065
		return $share;
1066
	}
1067
1068
	/**
1069
	 * @param Share[] $shares
1070
	 * @param $userId
1071
	 * @return Share[] The updates shares if no update is found for a share return the original
1072
	 */
1073
	private function resolveGroupShares($shares, $userId) {
1074
		$result = [];
1075
1076
		$start = 0;
1077
		while(true) {
1078
			/** @var Share[] $shareSlice */
1079
			$shareSlice = array_slice($shares, $start, 100);
1080
			$start += 100;
1081
1082
			if ($shareSlice === []) {
1083
				break;
1084
			}
1085
1086
			/** @var int[] $ids */
1087
			$ids = [];
1088
			/** @var Share[] $shareMap */
1089
			$shareMap = [];
1090
1091
			foreach ($shareSlice as $share) {
1092
				$ids[] = (int)$share->getId();
1093
				$shareMap[$share->getId()] = $share;
1094
			}
1095
1096
			$qb = $this->dbConn->getQueryBuilder();
1097
1098
			$query = $qb->select('*')
1099
				->from('share')
1100
				->where($qb->expr()->in('parent', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1101
				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
1102
				->andWhere($qb->expr()->orX(
1103
					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1104
					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1105
				));
1106
1107
			$stmt = $query->execute();
1108
1109
			while($data = $stmt->fetch()) {
1110
				$shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
1111
				$shareMap[$data['parent']]->setStatus((int)$data['accepted']);
1112
				$shareMap[$data['parent']]->setTarget($data['file_target']);
1113
				$shareMap[$data['parent']]->setParent($data['parent']);
1114
			}
1115
1116
			$stmt->closeCursor();
1117
1118
			foreach ($shareMap as $share) {
1119
				$result[] = $share;
1120
			}
1121
		}
1122
1123
		return $result;
1124
	}
1125
1126
	/**
1127
	 * A user is deleted from the system
1128
	 * So clean up the relevant shares.
1129
	 *
1130
	 * @param string $uid
1131
	 * @param int $shareType
1132
	 */
1133
	public function userDeleted($uid, $shareType) {
1134
		$qb = $this->dbConn->getQueryBuilder();
1135
1136
		$qb->delete('share');
1137
1138
		if ($shareType === \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

1138
		if ($shareType === /** @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...
1139
			/*
1140
			 * Delete all user shares that are owned by this user
1141
			 * or that are received by this user
1142
			 */
1143
1144
			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\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

1144
			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
1145
1146
			$qb->andWhere(
1147
				$qb->expr()->orX(
1148
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1149
					$qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1150
				)
1151
			);
1152
		} else if ($shareType === \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

1152
		} else if ($shareType === /** @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...
1153
			/*
1154
			 * Delete all group shares that are owned by this user
1155
			 * Or special user group shares that are received by this user
1156
			 */
1157
			$qb->where(
1158
				$qb->expr()->andX(
1159
					$qb->expr()->orX(
1160
						$qb->expr()->eq('share_type', $qb->createNamedParameter(\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

1160
						$qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
1161
						$qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP))
1162
					),
1163
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid))
1164
				)
1165
			);
1166
1167
			$qb->orWhere(
1168
				$qb->expr()->andX(
1169
					$qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)),
1170
					$qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1171
				)
1172
			);
1173
		} else if ($shareType === \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

1173
		} else if ($shareType === /** @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...
1174
			/*
1175
			 * Delete all link shares owned by this user.
1176
			 * And all link shares initiated by this user (until #22327 is in)
1177
			 */
1178
			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\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

1178
			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
1179
1180
			$qb->andWhere(
1181
				$qb->expr()->orX(
1182
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1183
					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($uid))
1184
				)
1185
			);
1186
		}
1187
1188
		$qb->execute();
1189
	}
1190
1191
	/**
1192
	 * Delete all shares received by this group. As well as any custom group
1193
	 * shares for group members.
1194
	 *
1195
	 * @param string $gid
1196
	 */
1197
	public function groupDeleted($gid) {
1198
		/*
1199
		 * First delete all custom group shares for group members
1200
		 */
1201
		$qb = $this->dbConn->getQueryBuilder();
1202
		$qb->select('id')
1203
			->from('share')
1204
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\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

1204
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
1205
			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1206
1207
		$cursor = $qb->execute();
1208
		$ids = [];
1209
		while($row = $cursor->fetch()) {
1210
			$ids[] = (int)$row['id'];
1211
		}
1212
		$cursor->closeCursor();
1213
1214
		if (!empty($ids)) {
1215
			$chunks = array_chunk($ids, 100);
1216
			foreach ($chunks as $chunk) {
1217
				$qb->delete('share')
1218
					->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
1219
					->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1220
				$qb->execute();
1221
			}
1222
		}
1223
1224
		/*
1225
		 * Now delete all the group shares
1226
		 */
1227
		$qb = $this->dbConn->getQueryBuilder();
1228
		$qb->delete('share')
1229
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\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

1229
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
1230
			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1231
		$qb->execute();
1232
	}
1233
1234
	/**
1235
	 * Delete custom group shares to this group for this user
1236
	 *
1237
	 * @param string $uid
1238
	 * @param string $gid
1239
	 */
1240
	public function userDeletedFromGroup($uid, $gid) {
1241
		/*
1242
		 * Get all group shares
1243
		 */
1244
		$qb = $this->dbConn->getQueryBuilder();
1245
		$qb->select('id')
1246
			->from('share')
1247
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\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

1247
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
1248
			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1249
1250
		$cursor = $qb->execute();
1251
		$ids = [];
1252
		while($row = $cursor->fetch()) {
1253
			$ids[] = (int)$row['id'];
1254
		}
1255
		$cursor->closeCursor();
1256
1257
		if (!empty($ids)) {
1258
			$chunks = array_chunk($ids, 100);
1259
			foreach ($chunks as $chunk) {
1260
				/*
1261
				 * Delete all special shares wit this users for the found group shares
1262
				 */
1263
				$qb->delete('share')
1264
					->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
1265
					->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($uid)))
1266
					->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1267
				$qb->execute();
1268
			}
1269
		}
1270
	}
1271
1272
	/**
1273
	 * @inheritdoc
1274
	 */
1275
	public function getAccessList($nodes, $currentAccess) {
1276
		$ids = [];
1277
		foreach ($nodes as $node) {
1278
			$ids[] = $node->getId();
1279
		}
1280
1281
		$qb = $this->dbConn->getQueryBuilder();
1282
1283
		$or = $qb->expr()->orX(
1284
			$qb->expr()->eq('share_type', $qb->createNamedParameter(\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

1284
			$qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
1285
			$qb->expr()->eq('share_type', $qb->createNamedParameter(\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

1285
			$qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
1286
			$qb->expr()->eq('share_type', $qb->createNamedParameter(\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

1286
			$qb->expr()->eq('share_type', $qb->createNamedParameter(/** @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...
1287
		);
1288
1289
		if ($currentAccess) {
1290
			$or->add($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)));
1291
		}
1292
1293
		$qb->select('id', 'parent', 'share_type', 'share_with', 'file_source', 'file_target', 'permissions')
1294
			->from('share')
1295
			->where(
1296
				$or
1297
			)
1298
			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1299
			->andWhere($qb->expr()->orX(
1300
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1301
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1302
			));
1303
		$cursor = $qb->execute();
1304
1305
		$users = [];
1306
		$link = false;
1307
		while($row = $cursor->fetch()) {
1308
			$type = (int)$row['share_type'];
1309
			if ($type === \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

1309
			if ($type === /** @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...
1310
				$uid = $row['share_with'];
1311
				$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1312
				$users[$uid][$row['id']] = $row;
1313
			} else if ($type === \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

1313
			} else if ($type === /** @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...
1314
				$gid = $row['share_with'];
1315
				$group = $this->groupManager->get($gid);
1316
1317
				if ($group === null) {
1318
					continue;
1319
				}
1320
1321
				$userList = $group->getUsers();
1322
				foreach ($userList as $user) {
1323
					$uid = $user->getUID();
1324
					$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1325
					$users[$uid][$row['id']] = $row;
1326
				}
1327
			} else if ($type === \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

1327
			} else if ($type === /** @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...
1328
				$link = true;
1329
			} else if ($type === self::SHARE_TYPE_USERGROUP && $currentAccess === true) {
1330
				$uid = $row['share_with'];
1331
				$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1332
				$users[$uid][$row['id']] = $row;
1333
			}
1334
		}
1335
		$cursor->closeCursor();
1336
1337
		if ($currentAccess === true) {
1338
			$users = array_map([$this, 'filterSharesOfUser'], $users);
1339
			$users = array_filter($users);
1340
		} else {
1341
			$users = array_keys($users);
1342
		}
1343
1344
		return ['users' => $users, 'public' => $link];
1345
	}
1346
1347
	/**
1348
	 * For each user the path with the fewest slashes is returned
1349
	 * @param array $shares
1350
	 * @return array
1351
	 */
1352
	protected function filterSharesOfUser(array $shares) {
1353
		// Group shares when the user has a share exception
1354
		foreach ($shares as $id => $share) {
1355
			$type = (int) $share['share_type'];
1356
			$permissions = (int) $share['permissions'];
1357
1358
			if ($type === self::SHARE_TYPE_USERGROUP) {
1359
				unset($shares[$share['parent']]);
1360
1361
				if ($permissions === 0) {
1362
					unset($shares[$id]);
1363
				}
1364
			}
1365
		}
1366
1367
		$best = [];
1368
		$bestDepth = 0;
1369
		foreach ($shares as $id => $share) {
1370
			$depth = substr_count($share['file_target'], '/');
1371
			if (empty($best) || $depth < $bestDepth) {
1372
				$bestDepth = $depth;
1373
				$best = [
1374
					'node_id' => $share['file_source'],
1375
					'node_path' => $share['file_target'],
1376
				];
1377
			}
1378
		}
1379
1380
		return $best;
1381
	}
1382
1383
	/**
1384
	 * propagate notes to the recipients
1385
	 *
1386
	 * @param IShare $share
1387
	 * @throws \OCP\Files\NotFoundException
1388
	 */
1389
	private function propagateNote(IShare $share) {
1390
		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

1390
		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...
1391
			$user = $this->userManager->get($share->getSharedWith());
1392
			$this->sendNote([$user], $share);
1393
		} 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

1393
		} 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...
1394
			$group = $this->groupManager->get($share->getSharedWith());
1395
			$groupMembers = $group->getUsers();
1396
			$this->sendNote($groupMembers, $share);
1397
		}
1398
	}
1399
1400
	/**
1401
	 * send note by mail
1402
	 *
1403
	 * @param array $recipients
1404
	 * @param IShare $share
1405
	 * @throws \OCP\Files\NotFoundException
1406
	 */
1407
	private function sendNote(array $recipients, IShare $share) {
1408
1409
		$toList = [];
1410
1411
		foreach ($recipients as $recipient) {
1412
			/** @var IUser $recipient */
1413
			$email = $recipient->getEMailAddress();
1414
			if ($email) {
1415
				$toList[$email] = $recipient->getDisplayName();
1416
			}
1417
		}
1418
1419
		if (!empty($toList)) {
1420
1421
			$filename = $share->getNode()->getName();
1422
			$initiator = $share->getSharedBy();
1423
			$note = $share->getNote();
1424
1425
			$initiatorUser = $this->userManager->get($initiator);
1426
			$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
1427
			$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
1428
			$plainHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
1429
			$htmlHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
1430
			$message = $this->mailer->createMessage();
1431
1432
			$emailTemplate = $this->mailer->createEMailTemplate('defaultShareProvider.sendNote');
1433
1434
			$emailTemplate->setSubject($this->l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
1435
			$emailTemplate->addHeader();
1436
			$emailTemplate->addHeading($htmlHeading, $plainHeading);
1437
			$emailTemplate->addBodyText(htmlspecialchars($note), $note);
1438
1439
			$link = $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]);
1440
			$emailTemplate->addBodyButton(
1441
				$this->l->t('Open »%s«', [$filename]),
1442
				$link
1443
			);
1444
1445
1446
			// The "From" contains the sharers name
1447
			$instanceName = $this->defaults->getName();
1448
			$senderName = $this->l->t(
1449
				'%1$s via %2$s',
1450
				[
1451
					$initiatorDisplayName,
1452
					$instanceName
1453
				]
1454
			);
1455
			$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
1456
			if ($initiatorEmailAddress !== null) {
1457
				$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
1458
				$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
1459
			} else {
1460
				$emailTemplate->addFooter();
1461
			}
1462
1463
			if (count($toList) === 1) {
1464
				$message->setTo($toList);
1465
			} else {
1466
				$message->setTo([]);
1467
				$message->setBcc($toList);
1468
			}
1469
			$message->useTemplate($emailTemplate);
1470
			$this->mailer->send($message);
1471
		}
1472
1473
	}
1474
1475
	public function getAllShares(): iterable {
1476
		$qb = $this->dbConn->getQueryBuilder();
1477
1478
		$qb->select('*')
1479
			->from('share')
1480
			->where(
1481
				$qb->expr()->orX(
1482
					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_USER)),
1483
					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_GROUP)),
1484
					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_LINK))
1485
				)
1486
			);
1487
1488
		$cursor = $qb->execute();
1489
		while($data = $cursor->fetch()) {
1490
			try {
1491
				$share = $this->createShare($data);
1492
			} catch (InvalidShare $e) {
1493
				continue;
1494
			}
1495
1496
			yield $share;
1497
		}
1498
		$cursor->closeCursor();
1499
	}
1500
}
1501