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

DefaultShareProvider::sendNote()   B

Complexity

Conditions 8
Paths 51

Size

Total Lines 64
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 42
nc 51
nop 2
dl 0
loc 64
rs 8.0035
c 0
b 0
f 0

How to fix   Long Method   

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
namespace OC\Share20;
31
32
use OC\Files\Cache\Cache;
33
use OCP\Defaults;
34
use OCP\Files\Folder;
35
use OCP\IL10N;
36
use OCP\IURLGenerator;
37
use OCP\IUser;
38
use OCP\Mail\IMailer;
39
use OCP\Share\IShare;
40
use OCP\Share\IShareHelper;
41
use OCP\Share\IShareProvider;
42
use OC\Share20\Exception\InvalidShare;
43
use OC\Share20\Exception\ProviderException;
44
use OCP\Share\Exceptions\ShareNotFound;
45
use OC\Share20\Exception\BackendError;
46
use OCP\DB\QueryBuilder\IQueryBuilder;
47
use OCP\IGroup;
48
use OCP\IGroupManager;
49
use OCP\IUserManager;
50
use OCP\Files\IRootFolder;
51
use OCP\IDBConnection;
52
use OCP\Files\Node;
53
54
/**
55
 * Class DefaultShareProvider
56
 *
57
 * @package OC\Share20
58
 */
59
class DefaultShareProvider implements IShareProvider {
60
61
	// Special share type for user modified group shares
62
	const SHARE_TYPE_USERGROUP = 2;
63
64
	/** @var IDBConnection */
65
	private $dbConn;
66
67
	/** @var IUserManager */
68
	private $userManager;
69
70
	/** @var IGroupManager */
71
	private $groupManager;
72
73
	/** @var IRootFolder */
74
	private $rootFolder;
75
76
	/** @var IMailer */
77
	private $mailer;
78
79
	/** @var Defaults */
80
	private $defaults;
81
82
	/** @var IL10N */
83
	private $l;
84
85
	/** @var IURLGenerator */
86
	private $urlGenerator;
87
88
	/**
89
	 * DefaultShareProvider constructor.
90
	 *
91
	 * @param IDBConnection $connection
92
	 * @param IUserManager $userManager
93
	 * @param IGroupManager $groupManager
94
	 * @param IRootFolder $rootFolder
95
	 * @param IMailer $mailer ;
96
	 * @param Defaults $defaults
97
	 * @param IL10N $l
98
	 * @param IURLGenerator $urlGenerator
99
	 */
100
	public function __construct(
101
			IDBConnection $connection,
102
			IUserManager $userManager,
103
			IGroupManager $groupManager,
104
			IRootFolder $rootFolder,
105
			IMailer $mailer,
106
			Defaults $defaults,
107
			IL10N $l,
108
			IURLGenerator $urlGenerator) {
109
		$this->dbConn = $connection;
110
		$this->userManager = $userManager;
111
		$this->groupManager = $groupManager;
112
		$this->rootFolder = $rootFolder;
113
		$this->mailer = $mailer;
114
		$this->defaults = $defaults;
115
		$this->l = $l;
116
		$this->urlGenerator = $urlGenerator;
117
	}
118
119
	/**
120
	 * Return the identifier of this provider.
121
	 *
122
	 * @return string Containing only [a-zA-Z0-9]
123
	 */
124
	public function identifier() {
125
		return 'ocinternal';
126
	}
127
128
	/**
129
	 * Share a path
130
	 *
131
	 * @param \OCP\Share\IShare $share
132
	 * @return \OCP\Share\IShare The share object
133
	 * @throws ShareNotFound
134
	 * @throws \Exception
135
	 */
136
	public function create(\OCP\Share\IShare $share) {
137
		$qb = $this->dbConn->getQueryBuilder();
138
139
		$qb->insert('share');
140
		$qb->setValue('share_type', $qb->createNamedParameter($share->getShareType()));
141
142
		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

142
		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...
143
			//Set the UID of the user we share with
144
			$qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
145
			$qb->setValue('accepted', $qb->createNamedParameter(IShare::STATUS_PENDING));
146
		} 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

146
		} 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...
147
			//Set the GID of the group we share with
148
			$qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
149
		} 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

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

241
		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...
242
			/*
243
			 * We allow updating the recipient on user shares.
244
			 */
245
			$qb = $this->dbConn->getQueryBuilder();
246
			$qb->update('share')
247
				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
248
				->set('share_with', $qb->createNamedParameter($share->getSharedWith()))
249
				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
250
				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
251
				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
252
				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
253
				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
254
				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
255
				->set('note', $qb->createNamedParameter($share->getNote()))
256
				->set('accepted', $qb->createNamedParameter($share->getStatus()))
257
				->execute();
258
		} 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

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

296
		} 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...
297
			$qb = $this->dbConn->getQueryBuilder();
298
			$qb->update('share')
299
				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
300
				->set('password', $qb->createNamedParameter($share->getPassword()))
301
				->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
302
				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
303
				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
304
				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
305
				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
306
				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
307
				->set('token', $qb->createNamedParameter($share->getToken()))
308
				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
309
				->set('note', $qb->createNamedParameter($share->getNote()))
310
				->set('label', $qb->createNamedParameter($share->getLabel()))
311
				->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

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

407
						/** @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...
408
						\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

408
						/** @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...
409
						\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

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

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

566
				$qb->expr()->eq('parent', $qb->createNamedParameter($share->/** @scrutinizer ignore-call */ getParent()))
Loading history...
567
			)->andWhere(
568
				$qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP))
569
			)->andWhere(
570
				$qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))
571
			);
572
573
		$qb->execute();
574
575
		return $this->getShareById($share->getId(), $recipient);
576
	}
577
578
	/**
579
	 * @inheritdoc
580
	 */
581
	public function move(\OCP\Share\IShare $share, $recipient) {
582
		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

582
		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...
583
			// Just update the target
584
			$qb = $this->dbConn->getQueryBuilder();
585
			$qb->update('share')
586
				->set('file_target', $qb->createNamedParameter($share->getTarget()))
587
				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
588
				->execute();
589
590
		} 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

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

649
			$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...
650
			$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

650
			$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...
651
			$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

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

747
						/** @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...
748
						\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

748
						/** @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...
749
						\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

749
						/** @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...
750
					], IQueryBuilder::PARAM_INT_ARRAY)
751
				)
752
			)
753
			->andWhere($qb->expr()->orX(
754
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
755
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
756
			));
757
758
		$cursor = $qb->execute();
759
		$data = $cursor->fetch();
760
		$cursor->closeCursor();
761
762
		if ($data === false) {
763
			throw new ShareNotFound();
764
		}
765
766
		try {
767
			$share = $this->createShare($data);
768
		} catch (InvalidShare $e) {
769
			throw new ShareNotFound();
770
		}
771
772
		// If the recipient is set for a group share resolve to that user
773
		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

773
		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...
774
			$share = $this->resolveGroupShares([$share], $recipientId)[0];
775
		}
776
777
		return $share;
778
	}
779
780
	/**
781
	 * Get shares for a given path
782
	 *
783
	 * @param \OCP\Files\Node $path
784
	 * @return \OCP\Share\IShare[]
785
	 */
786
	public function getSharesByPath(Node $path) {
787
		$qb = $this->dbConn->getQueryBuilder();
788
789
		$cursor = $qb->select('*')
790
			->from('share')
791
			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
792
			->andWhere(
793
				$qb->expr()->orX(
794
					$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

794
					$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...
795
					$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

795
					$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...
796
				)
797
			)
798
			->andWhere($qb->expr()->orX(
799
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
800
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
801
			))
802
			->execute();
803
804
		$shares = [];
805
		while($data = $cursor->fetch()) {
806
			$shares[] = $this->createShare($data);
807
		}
808
		$cursor->closeCursor();
809
810
		return $shares;
811
	}
812
813
	/**
814
	 * Returns whether the given database result can be interpreted as
815
	 * a share with accessible file (not trashed, not deleted)
816
	 */
817
	private function isAccessibleResult($data) {
818
		// exclude shares leading to deleted file entries
819
		if ($data['fileid'] === null) {
820
			return false;
821
		}
822
823
		// exclude shares leading to trashbin on home storages
824
		$pathSections = explode('/', $data['path'], 2);
825
		// FIXME: would not detect rare md5'd home storage case properly
826
		if ($pathSections[0] !== 'files'
827
		    	&& in_array(explode(':', $data['storage_string_id'], 2)[0], array('home', 'object'))) {
828
			return false;
829
		}
830
		return true;
831
	}
832
833
	/**
834
	 * @inheritdoc
835
	 */
836
	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
837
		/** @var Share[] $shares */
838
		$shares = [];
839
840
		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

840
		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...
841
			//Get shares directly with this user
842
			$qb = $this->dbConn->getQueryBuilder();
843
			$qb->select('s.*',
844
				'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
845
				'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
846
				'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
847
			)
848
				->selectAlias('st.id', 'storage_string_id')
849
				->from('share', 's')
850
				->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
851
				->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'));
852
853
			// Order by id
854
			$qb->orderBy('s.id');
855
856
			// Set limit and offset
857
			if ($limit !== -1) {
858
				$qb->setMaxResults($limit);
859
			}
860
			$qb->setFirstResult($offset);
861
862
			$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

862
			$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...
863
				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
864
				->andWhere($qb->expr()->orX(
865
					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
866
					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
867
				));
868
869
			// Filter by node if provided
870
			if ($node !== null) {
871
				$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
872
			}
873
874
			$cursor = $qb->execute();
875
876
			while($data = $cursor->fetch()) {
877
				if ($this->isAccessibleResult($data)) {
878
					$shares[] = $this->createShare($data);
879
				}
880
			}
881
			$cursor->closeCursor();
882
883
		} 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

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

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

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

1018
		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...
1019
			$share->setSharedWith($data['share_with']);
1020
			$user = $this->userManager->get($data['share_with']);
1021
			if ($user !== null) {
1022
				$share->setSharedWithDisplayName($user->getDisplayName());
1023
			}
1024
		} 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

1024
		} 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...
1025
			$share->setSharedWith($data['share_with']);
1026
		} 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

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

1127
		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...
1128
			/*
1129
			 * Delete all user shares that are owned by this user
1130
			 * or that are received by this user
1131
			 */
1132
1133
			$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

1133
			$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...
1134
1135
			$qb->andWhere(
1136
				$qb->expr()->orX(
1137
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1138
					$qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1139
				)
1140
			);
1141
		} 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

1141
		} 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...
1142
			/*
1143
			 * Delete all group shares that are owned by this user
1144
			 * Or special user group shares that are received by this user
1145
			 */
1146
			$qb->where(
1147
				$qb->expr()->andX(
1148
					$qb->expr()->orX(
1149
						$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

1149
						$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...
1150
						$qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP))
1151
					),
1152
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid))
1153
				)
1154
			);
1155
1156
			$qb->orWhere(
1157
				$qb->expr()->andX(
1158
					$qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)),
1159
					$qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1160
				)
1161
			);
1162
		} 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

1162
		} 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...
1163
			/*
1164
			 * Delete all link shares owned by this user.
1165
			 * And all link shares initiated by this user (until #22327 is in)
1166
			 */
1167
			$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

1167
			$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...
1168
1169
			$qb->andWhere(
1170
				$qb->expr()->orX(
1171
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1172
					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($uid))
1173
				)
1174
			);
1175
		}
1176
1177
		$qb->execute();
1178
	}
1179
1180
	/**
1181
	 * Delete all shares received by this group. As well as any custom group
1182
	 * shares for group members.
1183
	 *
1184
	 * @param string $gid
1185
	 */
1186
	public function groupDeleted($gid) {
1187
		/*
1188
		 * First delete all custom group shares for group members
1189
		 */
1190
		$qb = $this->dbConn->getQueryBuilder();
1191
		$qb->select('id')
1192
			->from('share')
1193
			->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

1193
			->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...
1194
			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1195
1196
		$cursor = $qb->execute();
1197
		$ids = [];
1198
		while($row = $cursor->fetch()) {
1199
			$ids[] = (int)$row['id'];
1200
		}
1201
		$cursor->closeCursor();
1202
1203
		if (!empty($ids)) {
1204
			$chunks = array_chunk($ids, 100);
1205
			foreach ($chunks as $chunk) {
1206
				$qb->delete('share')
1207
					->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)))
1208
					->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1209
				$qb->execute();
1210
			}
1211
		}
1212
1213
		/*
1214
		 * Now delete all the group shares
1215
		 */
1216
		$qb = $this->dbConn->getQueryBuilder();
1217
		$qb->delete('share')
1218
			->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

1218
			->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...
1219
			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1220
		$qb->execute();
1221
	}
1222
1223
	/**
1224
	 * Delete custom group shares to this group for this user
1225
	 *
1226
	 * @param string $uid
1227
	 * @param string $gid
1228
	 */
1229
	public function userDeletedFromGroup($uid, $gid) {
1230
		/*
1231
		 * Get all group shares
1232
		 */
1233
		$qb = $this->dbConn->getQueryBuilder();
1234
		$qb->select('id')
1235
			->from('share')
1236
			->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

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

1273
			$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...
1274
			$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

1274
			$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...
1275
			$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

1275
			$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...
1276
		);
1277
1278
		if ($currentAccess) {
1279
			$or->add($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP)));
1280
		}
1281
1282
		$qb->select('id', 'parent', 'share_type', 'share_with', 'file_source', 'file_target', 'permissions')
1283
			->from('share')
1284
			->where(
1285
				$or
1286
			)
1287
			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1288
			->andWhere($qb->expr()->orX(
1289
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1290
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1291
			));
1292
		$cursor = $qb->execute();
1293
1294
		$users = [];
1295
		$link = false;
1296
		while($row = $cursor->fetch()) {
1297
			$type = (int)$row['share_type'];
1298
			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

1298
			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...
1299
				$uid = $row['share_with'];
1300
				$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1301
				$users[$uid][$row['id']] = $row;
1302
			} 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

1302
			} 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...
1303
				$gid = $row['share_with'];
1304
				$group = $this->groupManager->get($gid);
1305
1306
				if ($group === null) {
1307
					continue;
1308
				}
1309
1310
				$userList = $group->getUsers();
1311
				foreach ($userList as $user) {
1312
					$uid = $user->getUID();
1313
					$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1314
					$users[$uid][$row['id']] = $row;
1315
				}
1316
			} 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

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

1379
		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...
1380
			$user = $this->userManager->get($share->getSharedWith());
1381
			$this->sendNote([$user], $share);
1382
		} 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

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