Passed
Push — master ( efd025...251a4d )
by Roeland
16:39 queued 12s
created

ShareByMailProvider::create()   B

Complexity

Conditions 8
Paths 9

Size

Total Lines 35
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 20
nc 9
nop 1
dl 0
loc 35
rs 8.4444
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Bjoern Schiessle <[email protected]>
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Bjoern Schiessle <[email protected]>
7
 * @author Christoph Wurst <[email protected]>
8
 * @author comradekingu <[email protected]>
9
 * @author Daniel Calviño Sánchez <[email protected]>
10
 * @author exner104 <[email protected]>
11
 * @author Frederic Werner <[email protected]>
12
 * @author Joas Schilling <[email protected]>
13
 * @author Lukas Reschke <[email protected]>
14
 * @author Morris Jobke <[email protected]>
15
 * @author Robin Appelman <[email protected]>
16
 * @author Roeland Jago Douma <[email protected]>
17
 * @author rubo77 <[email protected]>
18
 * @author Stephan Müller <[email protected]>
19
 *
20
 * @license GNU AGPL version 3 or any later version
21
 *
22
 * This program is free software: you can redistribute it and/or modify
23
 * it under the terms of the GNU Affero General Public License as
24
 * published by the Free Software Foundation, either version 3 of the
25
 * License, or (at your option) any later version.
26
 *
27
 * This program is distributed in the hope that it will be useful,
28
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30
 * GNU Affero General Public License for more details.
31
 *
32
 * You should have received a copy of the GNU Affero General Public License
33
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
34
 *
35
 */
36
37
namespace OCA\ShareByMail;
38
39
use OC\CapabilitiesManager;
40
use OC\HintException;
41
use OC\Share20\Exception\InvalidShare;
42
use OC\Share20\Share;
43
use OC\User\NoUserException;
44
use OCA\ShareByMail\Settings\SettingsManager;
45
use OCP\Activity\IManager;
46
use OCP\DB\QueryBuilder\IQueryBuilder;
47
use OCP\Defaults;
48
use OCP\Files\Folder;
49
use OCP\Files\IRootFolder;
50
use OCP\Files\Node;
51
use OCP\IDBConnection;
52
use OCP\IL10N;
53
use OCP\ILogger;
54
use OCP\IURLGenerator;
55
use OCP\IUser;
56
use OCP\IUserManager;
57
use OCP\Mail\IMailer;
58
use OCP\Security\IHasher;
59
use OCP\Security\ISecureRandom;
60
use OCP\Share\Exceptions\GenericShareException;
61
use OCP\Share\Exceptions\ShareNotFound;
62
use OCP\Share\IShare;
63
use OCP\Share\IShareProvider;
64
65
/**
66
 * Class ShareByMail
67
 *
68
 * @package OCA\ShareByMail
69
 */
70
class ShareByMailProvider implements IShareProvider {
71
72
	/** @var  IDBConnection */
73
	private $dbConnection;
74
75
	/** @var ILogger */
76
	private $logger;
77
78
	/** @var ISecureRandom */
79
	private $secureRandom;
80
81
	/** @var IUserManager */
82
	private $userManager;
83
84
	/** @var IRootFolder */
85
	private $rootFolder;
86
87
	/** @var IL10N */
88
	private $l;
89
90
	/** @var IMailer */
91
	private $mailer;
92
93
	/** @var IURLGenerator */
94
	private $urlGenerator;
95
96
	/** @var IManager  */
97
	private $activityManager;
98
99
	/** @var SettingsManager */
100
	private $settingsManager;
101
102
	/** @var Defaults */
103
	private $defaults;
104
105
	/** @var IHasher */
106
	private $hasher;
107
108
	/** @var  CapabilitiesManager */
109
	private $capabilitiesManager;
110
111
	/**
112
	 * Return the identifier of this provider.
113
	 *
114
	 * @return string Containing only [a-zA-Z0-9]
115
	 */
116
	public function identifier() {
117
		return 'ocMailShare';
118
	}
119
120
	/**
121
	 * DefaultShareProvider constructor.
122
	 *
123
	 * @param IDBConnection $connection
124
	 * @param ISecureRandom $secureRandom
125
	 * @param IUserManager $userManager
126
	 * @param IRootFolder $rootFolder
127
	 * @param IL10N $l
128
	 * @param ILogger $logger
129
	 * @param IMailer $mailer
130
	 * @param IURLGenerator $urlGenerator
131
	 * @param IManager $activityManager
132
	 * @param SettingsManager $settingsManager
133
	 * @param Defaults $defaults
134
	 * @param IHasher $hasher
135
	 * @param CapabilitiesManager $capabilitiesManager
136
	 */
137
	public function __construct(
138
		IDBConnection $connection,
139
		ISecureRandom $secureRandom,
140
		IUserManager $userManager,
141
		IRootFolder $rootFolder,
142
		IL10N $l,
143
		ILogger $logger,
144
		IMailer $mailer,
145
		IURLGenerator $urlGenerator,
146
		IManager $activityManager,
147
		SettingsManager $settingsManager,
148
		Defaults $defaults,
149
		IHasher $hasher,
150
		CapabilitiesManager $capabilitiesManager
151
	) {
152
		$this->dbConnection = $connection;
153
		$this->secureRandom = $secureRandom;
154
		$this->userManager = $userManager;
155
		$this->rootFolder = $rootFolder;
156
		$this->l = $l;
157
		$this->logger = $logger;
158
		$this->mailer = $mailer;
159
		$this->urlGenerator = $urlGenerator;
160
		$this->activityManager = $activityManager;
161
		$this->settingsManager = $settingsManager;
162
		$this->defaults = $defaults;
163
		$this->hasher = $hasher;
164
		$this->capabilitiesManager = $capabilitiesManager;
165
	}
166
167
	/**
168
	 * Share a path
169
	 *
170
	 * @param IShare $share
171
	 * @return IShare The share object
172
	 * @throws ShareNotFound
173
	 * @throws \Exception
174
	 */
175
	public function create(IShare $share) {
176
		$shareWith = $share->getSharedWith();
177
		/*
178
		 * Check if file is not already shared with the remote user
179
		 */
180
		$alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_EMAIL, $share->getNode(), 1, 0);
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

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

180
		$alreadyShared = $this->getSharedWith($shareWith, /** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL, $share->getNode(), 1, 0);

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

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

Loading history...
181
		if (!empty($alreadyShared)) {
182
			$message = 'Sharing %1$s failed, this item is already shared with %2$s';
183
			$message_t = $this->l->t('Sharing %1$s failed, this item is already shared with %2$s', [$share->getNode()->getName(), $shareWith]);
184
			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
185
			throw new \Exception($message_t);
186
		}
187
188
		// if the admin enforces a password for all mail shares we create a
189
		// random password and send it to the recipient
190
		$password = $share->getPassword() ?: '';
191
		$passwordEnforced = $this->settingsManager->enforcePasswordProtection();
192
		if ($passwordEnforced && empty($password)) {
193
			$password = $this->autoGeneratePassword($share);
194
		}
195
196
		if (!empty($password)) {
197
			$share->setPassword($this->hasher->hash($password));
198
		}
199
200
		$shareId = $this->createMailShare($share);
201
		$send = $this->sendPassword($share, $password);
202
		if ($passwordEnforced && $send === false) {
203
			$this->sendPasswordToOwner($share, $password);
204
		}
205
206
		$this->createShareActivity($share);
207
		$data = $this->getRawShare($shareId);
208
209
		return $this->createShareObject($data);
210
	}
211
212
	/**
213
	 * auto generate password in case of password enforcement on mail shares
214
	 *
215
	 * @param IShare $share
216
	 * @return string
217
	 * @throws \Exception
218
	 */
219
	protected function autoGeneratePassword($share) {
220
		$initiatorUser = $this->userManager->get($share->getSharedBy());
221
		$initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
222
		$allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
223
224
		if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
225
			throw new \Exception(
226
				$this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.")
227
			);
228
		}
229
230
		$passwordPolicy = $this->getPasswordPolicy();
231
		$passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS;
232
		$passwordLength = 8;
233
		if (!empty($passwordPolicy)) {
234
			$passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength;
235
			$passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : '';
236
		}
237
238
		$password = $this->secureRandom->generate($passwordLength, $passwordCharset);
239
240
		return $password;
241
	}
242
243
	/**
244
	 * get password policy
245
	 *
246
	 * @return array
247
	 */
248
	protected function getPasswordPolicy() {
249
		$capabilities = $this->capabilitiesManager->getCapabilities();
250
		if (isset($capabilities['password_policy'])) {
251
			return $capabilities['password_policy'];
252
		}
253
254
		return [];
255
	}
256
257
	/**
258
	 * create activity if a file/folder was shared by mail
259
	 *
260
	 * @param IShare $share
261
	 * @param string $type
262
	 */
263
	protected function createShareActivity(IShare $share, string $type = 'share') {
264
		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
265
266
		$this->publishActivity(
267
			$type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_SELF : Activity::SUBJECT_UNSHARED_EMAIL_SELF,
268
			[$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
269
			$share->getSharedBy(),
270
			$share->getNode()->getId(),
271
			(string) $userFolder->getRelativePath($share->getNode()->getPath())
272
		);
273
274
		if ($share->getShareOwner() !== $share->getSharedBy()) {
275
			$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
276
			$fileId = $share->getNode()->getId();
277
			$nodes = $ownerFolder->getById($fileId);
278
			$ownerPath = $nodes[0]->getPath();
279
			$this->publishActivity(
280
				$type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_BY : Activity::SUBJECT_UNSHARED_EMAIL_BY,
281
				[$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
282
				$share->getShareOwner(),
283
				$fileId,
284
				(string) $ownerFolder->getRelativePath($ownerPath)
285
			);
286
		}
287
	}
288
289
	/**
290
	 * create activity if a file/folder was shared by mail
291
	 *
292
	 * @param IShare $share
293
	 * @param string $sharedWith
294
	 * @param bool $sendToSelf
295
	 */
296
	protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) {
297
		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
298
299
		if ($sendToSelf) {
300
			$this->publishActivity(
301
				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
302
				[$userFolder->getRelativePath($share->getNode()->getPath())],
303
				$share->getSharedBy(),
304
				$share->getNode()->getId(),
305
				(string) $userFolder->getRelativePath($share->getNode()->getPath())
306
			);
307
		} else {
308
			$this->publishActivity(
309
				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
310
				[$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
311
				$share->getSharedBy(),
312
				$share->getNode()->getId(),
313
				(string) $userFolder->getRelativePath($share->getNode()->getPath())
314
			);
315
		}
316
	}
317
318
319
	/**
320
	 * publish activity if a file/folder was shared by mail
321
	 *
322
	 * @param string $subject
323
	 * @param array $parameters
324
	 * @param string $affectedUser
325
	 * @param int $fileId
326
	 * @param string $filePath
327
	 */
328
	protected function publishActivity(string $subject, array $parameters, string $affectedUser, int $fileId, string $filePath) {
329
		$event = $this->activityManager->generateEvent();
330
		$event->setApp('sharebymail')
331
			->setType('shared')
332
			->setSubject($subject, $parameters)
333
			->setAffectedUser($affectedUser)
334
			->setObject('files', $fileId, $filePath);
335
		$this->activityManager->publish($event);
336
	}
337
338
	/**
339
	 * @param IShare $share
340
	 * @return int
341
	 * @throws \Exception
342
	 */
343
	protected function createMailShare(IShare $share) {
344
		$share->setToken($this->generateToken());
345
		$shareId = $this->addShareToDB(
346
			$share->getNodeId(),
347
			$share->getNodeType(),
348
			$share->getSharedWith(),
349
			$share->getSharedBy(),
350
			$share->getShareOwner(),
351
			$share->getPermissions(),
352
			$share->getToken(),
353
			$share->getPassword(),
354
			$share->getSendPasswordByTalk(),
355
			$share->getHideDownload()
356
		);
357
358
		try {
359
			$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
360
				['token' => $share->getToken()]);
361
			$this->sendMailNotification(
362
				$share->getNode()->getName(),
363
				$link,
364
				$share->getSharedBy(),
365
				$share->getSharedWith(),
366
				$share->getExpirationDate()
367
			);
368
		} catch (HintException $hintException) {
369
			$this->logger->logException($hintException, [
370
				'message' => 'Failed to send share by mail.',
371
				'level' => ILogger::ERROR,
372
				'app' => 'sharebymail',
373
			]);
374
			$this->removeShareFromTable($shareId);
375
			throw $hintException;
376
		} catch (\Exception $e) {
377
			$this->logger->logException($e, [
378
				'message' => 'Failed to send share by mail.',
379
				'level' => ILogger::ERROR,
380
				'app' => 'sharebymail',
381
			]);
382
			$this->removeShareFromTable($shareId);
383
			throw new HintException('Failed to send share by mail',
384
				$this->l->t('Failed to send share by email'));
385
		}
386
387
		return $shareId;
388
	}
389
390
	/**
391
	 * @param string $filename
392
	 * @param string $link
393
	 * @param string $initiator
394
	 * @param string $shareWith
395
	 * @param \DateTime|null $expiration
396
	 * @throws \Exception If mail couldn't be sent
397
	 */
398
	protected function sendMailNotification($filename,
399
											$link,
400
											$initiator,
401
											$shareWith,
402
											\DateTime $expiration = null) {
403
		$initiatorUser = $this->userManager->get($initiator);
404
		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
405
		$message = $this->mailer->createMessage();
406
407
		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [
408
			'filename' => $filename,
409
			'link' => $link,
410
			'initiator' => $initiatorDisplayName,
411
			'expiration' => $expiration,
412
			'shareWith' => $shareWith,
413
		]);
414
415
		$emailTemplate->setSubject($this->l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]));
416
		$emailTemplate->addHeader();
417
		$emailTemplate->addHeading($this->l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
418
		$text = $this->l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
419
420
		$emailTemplate->addBodyText(
421
			htmlspecialchars($text . ' ' . $this->l->t('Click the button below to open it.')),
422
			$text
423
		);
424
		$emailTemplate->addBodyButton(
425
			$this->l->t('Open »%s«', [$filename]),
426
			$link
427
		);
428
429
		$message->setTo([$shareWith]);
430
431
		// The "From" contains the sharers name
432
		$instanceName = $this->defaults->getName();
433
		$senderName = $this->l->t(
434
			'%1$s via %2$s',
435
			[
436
				$initiatorDisplayName,
437
				$instanceName
438
			]
439
		);
440
		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
441
442
		// The "Reply-To" is set to the sharer if an mail address is configured
443
		// also the default footer contains a "Do not reply" which needs to be adjusted.
444
		$initiatorEmail = $initiatorUser->getEMailAddress();
445
		if ($initiatorEmail !== null) {
446
			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
447
			$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
448
		} else {
449
			$emailTemplate->addFooter();
450
		}
451
452
		$message->useTemplate($emailTemplate);
453
		$this->mailer->send($message);
454
	}
455
456
	/**
457
	 * send password to recipient of a mail share
458
	 *
459
	 * @param IShare $share
460
	 * @param string $password
461
	 * @return bool
462
	 */
463
	protected function sendPassword(IShare $share, $password) {
464
		$filename = $share->getNode()->getName();
465
		$initiator = $share->getSharedBy();
466
		$shareWith = $share->getSharedWith();
467
468
		if ($password === '' || $this->settingsManager->sendPasswordByMail() === false || $share->getSendPasswordByTalk()) {
469
			return false;
470
		}
471
472
		$initiatorUser = $this->userManager->get($initiator);
473
		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
474
		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
475
476
		$plainBodyPart = $this->l->t("%1\$s shared »%2\$s« with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]);
477
		$htmlBodyPart = $this->l->t('%1$s shared »%2$s« with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
478
479
		$message = $this->mailer->createMessage();
480
481
		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [
482
			'filename' => $filename,
483
			'password' => $password,
484
			'initiator' => $initiatorDisplayName,
485
			'initiatorEmail' => $initiatorEmailAddress,
486
			'shareWith' => $shareWith,
487
		]);
488
489
		$emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared to you by %2$s', [$filename, $initiatorDisplayName]));
490
		$emailTemplate->addHeader();
491
		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
492
		$emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart);
493
		$emailTemplate->addBodyText($this->l->t('It is protected with the following password:'));
494
		$emailTemplate->addBodyText($password);
495
496
		// The "From" contains the sharers name
497
		$instanceName = $this->defaults->getName();
498
		$senderName = $this->l->t(
499
			'%1$s via %2$s',
500
			[
501
				$initiatorDisplayName,
502
				$instanceName
503
			]
504
		);
505
		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
506
		if ($initiatorEmailAddress !== null) {
507
			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
508
			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
509
		} else {
510
			$emailTemplate->addFooter();
511
		}
512
513
		$message->setTo([$shareWith]);
514
		$message->useTemplate($emailTemplate);
515
		$this->mailer->send($message);
516
517
		$this->createPasswordSendActivity($share, $shareWith, false);
518
519
		return true;
520
	}
521
522
	protected function sendNote(IShare $share) {
523
		$recipient = $share->getSharedWith();
524
525
526
		$filename = $share->getNode()->getName();
527
		$initiator = $share->getSharedBy();
528
		$note = $share->getNote();
529
530
		$initiatorUser = $this->userManager->get($initiator);
531
		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
532
		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
533
534
		$plainHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
535
		$htmlHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
536
537
		$message = $this->mailer->createMessage();
538
539
		$emailTemplate = $this->mailer->createEMailTemplate('shareByMail.sendNote');
540
541
		$emailTemplate->setSubject($this->l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
542
		$emailTemplate->addHeader();
543
		$emailTemplate->addHeading(htmlspecialchars($htmlHeading), $plainHeading);
544
		$emailTemplate->addBodyText(htmlspecialchars($note), $note);
545
546
		$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
547
			['token' => $share->getToken()]);
548
		$emailTemplate->addBodyButton(
549
			$this->l->t('Open »%s«', [$filename]),
550
			$link
551
		);
552
553
		// The "From" contains the sharers name
554
		$instanceName = $this->defaults->getName();
555
		$senderName = $this->l->t(
556
			'%1$s via %2$s',
557
			[
558
				$initiatorDisplayName,
559
				$instanceName
560
			]
561
		);
562
		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
563
		if ($initiatorEmailAddress !== null) {
564
			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
565
			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
566
		} else {
567
			$emailTemplate->addFooter();
568
		}
569
570
		$message->setTo([$recipient]);
571
		$message->useTemplate($emailTemplate);
572
		$this->mailer->send($message);
573
	}
574
575
	/**
576
	 * send auto generated password to the owner. This happens if the admin enforces
577
	 * a password for mail shares and forbid to send the password by mail to the recipient
578
	 *
579
	 * @param IShare $share
580
	 * @param string $password
581
	 * @return bool
582
	 * @throws \Exception
583
	 */
584
	protected function sendPasswordToOwner(IShare $share, $password) {
585
		$filename = $share->getNode()->getName();
586
		$initiator = $this->userManager->get($share->getSharedBy());
587
		$initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
588
		$initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
589
		$shareWith = $share->getSharedWith();
590
591
		if ($initiatorEMailAddress === null) {
592
			throw new \Exception(
593
				$this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.")
594
			);
595
		}
596
597
		$bodyPart = $this->l->t('You just shared »%1$s« with %2$s. The share was already sent to the recipient. Due to the security policies defined by the administrator of %3$s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient.', [$filename, $shareWith, $this->defaults->getName()]);
598
599
		$message = $this->mailer->createMessage();
600
		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [
601
			'filename' => $filename,
602
			'password' => $password,
603
			'initiator' => $initiatorDisplayName,
604
			'initiatorEmail' => $initiatorEMailAddress,
605
			'shareWith' => $shareWith,
606
		]);
607
608
		$emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared by you with %2$s', [$filename, $shareWith]));
609
		$emailTemplate->addHeader();
610
		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
611
		$emailTemplate->addBodyText($bodyPart);
612
		$emailTemplate->addBodyText($this->l->t('This is the password:'));
613
		$emailTemplate->addBodyText($password);
614
		$emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
615
		$emailTemplate->addFooter();
616
617
		$instanceName = $this->defaults->getName();
618
		$senderName = $this->l->t(
619
			'%1$s via %2$s',
620
			[
621
				$initiatorDisplayName,
622
				$instanceName
623
			]
624
		);
625
		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
626
		$message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
627
		$message->useTemplate($emailTemplate);
628
		$this->mailer->send($message);
629
630
		$this->createPasswordSendActivity($share, $shareWith, true);
631
632
		return true;
633
	}
634
635
	/**
636
	 * generate share token
637
	 *
638
	 * @return string
639
	 */
640
	protected function generateToken($size = 15) {
641
		$token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
642
		return $token;
643
	}
644
645
	/**
646
	 * Get all children of this share
647
	 *
648
	 * @param IShare $parent
649
	 * @return IShare[]
650
	 */
651
	public function getChildren(IShare $parent) {
652
		$children = [];
653
654
		$qb = $this->dbConnection->getQueryBuilder();
655
		$qb->select('*')
656
			->from('share')
657
			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
658
			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

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

658
			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL)))

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

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

Loading history...
659
			->orderBy('id');
660
661
		$cursor = $qb->execute();
662
		while ($data = $cursor->fetch()) {
663
			$children[] = $this->createShareObject($data);
664
		}
665
		$cursor->closeCursor();
666
667
		return $children;
668
	}
669
670
	/**
671
	 * add share to the database and return the ID
672
	 *
673
	 * @param int $itemSource
674
	 * @param string $itemType
675
	 * @param string $shareWith
676
	 * @param string $sharedBy
677
	 * @param string $uidOwner
678
	 * @param int $permissions
679
	 * @param string $token
680
	 * @param string $password
681
	 * @param bool $sendPasswordByTalk
682
	 * @param bool $hideDownload
683
	 * @return int
684
	 */
685
	protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password, $sendPasswordByTalk, $hideDownload) {
686
		$qb = $this->dbConnection->getQueryBuilder();
687
		$qb->insert('share')
688
			->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

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

688
			->setValue('share_type', $qb->createNamedParameter(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL))

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

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

Loading history...
689
			->setValue('item_type', $qb->createNamedParameter($itemType))
690
			->setValue('item_source', $qb->createNamedParameter($itemSource))
691
			->setValue('file_source', $qb->createNamedParameter($itemSource))
692
			->setValue('share_with', $qb->createNamedParameter($shareWith))
693
			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
694
			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
695
			->setValue('permissions', $qb->createNamedParameter($permissions))
696
			->setValue('token', $qb->createNamedParameter($token))
697
			->setValue('password', $qb->createNamedParameter($password))
698
			->setValue('password_by_talk', $qb->createNamedParameter($sendPasswordByTalk, IQueryBuilder::PARAM_BOOL))
699
			->setValue('stime', $qb->createNamedParameter(time()))
700
			->setValue('hide_download', $qb->createNamedParameter((int)$hideDownload, IQueryBuilder::PARAM_INT));
701
702
		/*
703
		 * Added to fix https://github.com/owncloud/core/issues/22215
704
		 * Can be removed once we get rid of ajax/share.php
705
		 */
706
		$qb->setValue('file_target', $qb->createNamedParameter(''));
707
708
		$qb->execute();
709
		$id = $qb->getLastInsertId();
710
711
		return (int)$id;
712
	}
713
714
	/**
715
	 * Update a share
716
	 *
717
	 * @param IShare $share
718
	 * @param string|null $plainTextPassword
719
	 * @return IShare The share object
720
	 */
721
	public function update(IShare $share, $plainTextPassword = null) {
722
		$originalShare = $this->getShareById($share->getId());
723
724
		// a real password was given
725
		$validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
726
727
		if ($validPassword && ($originalShare->getPassword() !== $share->getPassword() ||
728
								($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()))) {
729
			$this->sendPassword($share, $plainTextPassword);
730
		}
731
		/*
732
		 * We allow updating the permissions and password of mail shares
733
		 */
734
		$qb = $this->dbConnection->getQueryBuilder();
735
		$qb->update('share')
736
			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
737
			->set('permissions', $qb->createNamedParameter($share->getPermissions()))
738
			->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
739
			->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
740
			->set('password', $qb->createNamedParameter($share->getPassword()))
741
			->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
742
			->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
743
			->set('note', $qb->createNamedParameter($share->getNote()))
744
			->set('hide_download', $qb->createNamedParameter((int)$share->getHideDownload(), IQueryBuilder::PARAM_INT))
745
			->execute();
746
747
		if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
748
			$this->sendNote($share);
749
		}
750
751
		return $share;
752
	}
753
754
	/**
755
	 * @inheritdoc
756
	 */
757
	public function move(IShare $share, $recipient) {
758
		/**
759
		 * nothing to do here, mail shares are only outgoing shares
760
		 */
761
		return $share;
762
	}
763
764
	/**
765
	 * Delete a share (owner unShares the file)
766
	 *
767
	 * @param IShare $share
768
	 */
769
	public function delete(IShare $share) {
770
		try {
771
			$this->createShareActivity($share, 'unshare');
772
		} catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
773
		}
774
775
		$this->removeShareFromTable($share->getId());
776
	}
777
778
	/**
779
	 * @inheritdoc
780
	 */
781
	public function deleteFromSelf(IShare $share, $recipient) {
782
		// nothing to do here, mail shares are only outgoing shares
783
	}
784
785
	public function restore(IShare $share, string $recipient): IShare {
786
		throw new GenericShareException('not implemented');
787
	}
788
789
	/**
790
	 * @inheritdoc
791
	 */
792
	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
793
		$qb = $this->dbConnection->getQueryBuilder();
794
		$qb->select('*')
795
			->from('share');
796
797
		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

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

797
		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL)));

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

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

Loading history...
798
799
		/**
800
		 * Reshares for this user are shares where they are the owner.
801
		 */
802
		if ($reshares === false) {
803
			//Special case for old shares created via the web UI
804
			$or1 = $qb->expr()->andX(
805
				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
806
				$qb->expr()->isNull('uid_initiator')
807
			);
808
809
			$qb->andWhere(
810
				$qb->expr()->orX(
811
					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
812
					$or1
813
				)
814
			);
815
		} else {
816
			$qb->andWhere(
817
				$qb->expr()->orX(
818
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
819
					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
820
				)
821
			);
822
		}
823
824
		if ($node !== null) {
825
			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
826
		}
827
828
		if ($limit !== -1) {
829
			$qb->setMaxResults($limit);
830
		}
831
832
		$qb->setFirstResult($offset);
833
		$qb->orderBy('id');
834
835
		$cursor = $qb->execute();
836
		$shares = [];
837
		while ($data = $cursor->fetch()) {
838
			$shares[] = $this->createShareObject($data);
839
		}
840
		$cursor->closeCursor();
841
842
		return $shares;
843
	}
844
845
	/**
846
	 * @inheritdoc
847
	 */
848
	public function getShareById($id, $recipientId = null) {
849
		$qb = $this->dbConnection->getQueryBuilder();
850
851
		$qb->select('*')
852
			->from('share')
853
			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
854
			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

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

854
			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL)));

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

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

Loading history...
855
856
		$cursor = $qb->execute();
857
		$data = $cursor->fetch();
858
		$cursor->closeCursor();
859
860
		if ($data === false) {
861
			throw new ShareNotFound();
862
		}
863
864
		try {
865
			$share = $this->createShareObject($data);
866
		} catch (InvalidShare $e) {
867
			throw new ShareNotFound();
868
		}
869
870
		return $share;
871
	}
872
873
	/**
874
	 * Get shares for a given path
875
	 *
876
	 * @param \OCP\Files\Node $path
877
	 * @return IShare[]
878
	 */
879
	public function getSharesByPath(Node $path) {
880
		$qb = $this->dbConnection->getQueryBuilder();
881
882
		$cursor = $qb->select('*')
883
			->from('share')
884
			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
885
			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

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

885
			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL)))

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

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

Loading history...
886
			->execute();
887
888
		$shares = [];
889
		while ($data = $cursor->fetch()) {
890
			$shares[] = $this->createShareObject($data);
891
		}
892
		$cursor->closeCursor();
893
894
		return $shares;
895
	}
896
897
	/**
898
	 * @inheritdoc
899
	 */
900
	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
901
		/** @var IShare[] $shares */
902
		$shares = [];
903
904
		//Get shares directly with this user
905
		$qb = $this->dbConnection->getQueryBuilder();
906
		$qb->select('*')
907
			->from('share');
908
909
		// Order by id
910
		$qb->orderBy('id');
911
912
		// Set limit and offset
913
		if ($limit !== -1) {
914
			$qb->setMaxResults($limit);
915
		}
916
		$qb->setFirstResult($offset);
917
918
		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

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

918
		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL)));

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

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

Loading history...
919
		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
920
921
		// Filter by node if provided
922
		if ($node !== null) {
923
			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
924
		}
925
926
		$cursor = $qb->execute();
927
928
		while ($data = $cursor->fetch()) {
929
			$shares[] = $this->createShareObject($data);
930
		}
931
		$cursor->closeCursor();
932
933
934
		return $shares;
935
	}
936
937
	/**
938
	 * Get a share by token
939
	 *
940
	 * @param string $token
941
	 * @return IShare
942
	 * @throws ShareNotFound
943
	 */
944
	public function getShareByToken($token) {
945
		$qb = $this->dbConnection->getQueryBuilder();
946
947
		$cursor = $qb->select('*')
948
			->from('share')
949
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

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

949
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL)))

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

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

Loading history...
950
			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
951
			->execute();
952
953
		$data = $cursor->fetch();
954
955
		if ($data === false) {
956
			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
957
		}
958
959
		try {
960
			$share = $this->createShareObject($data);
961
		} catch (InvalidShare $e) {
962
			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
963
		}
964
965
		return $share;
966
	}
967
968
	/**
969
	 * remove share from table
970
	 *
971
	 * @param string $shareId
972
	 */
973
	protected function removeShareFromTable($shareId) {
974
		$qb = $this->dbConnection->getQueryBuilder();
975
		$qb->delete('share')
976
			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
977
		$qb->execute();
978
	}
979
980
	/**
981
	 * Create a share object from an database row
982
	 *
983
	 * @param array $data
984
	 * @return IShare
985
	 * @throws InvalidShare
986
	 * @throws ShareNotFound
987
	 */
988
	protected function createShareObject($data) {
989
		$share = new Share($this->rootFolder, $this->userManager);
990
		$share->setId((int)$data['id'])
991
			->setShareType((int)$data['share_type'])
992
			->setPermissions((int)$data['permissions'])
993
			->setTarget($data['file_target'])
994
			->setMailSend((bool)$data['mail_send'])
995
			->setNote($data['note'])
996
			->setToken($data['token']);
997
998
		$shareTime = new \DateTime();
999
		$shareTime->setTimestamp((int)$data['stime']);
1000
		$share->setShareTime($shareTime);
1001
		$share->setSharedWith($data['share_with']);
1002
		$share->setPassword($data['password']);
1003
		$share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1004
		$share->setHideDownload((bool)$data['hide_download']);
1005
1006
		if ($data['uid_initiator'] !== null) {
1007
			$share->setShareOwner($data['uid_owner']);
1008
			$share->setSharedBy($data['uid_initiator']);
1009
		} else {
1010
			//OLD SHARE
1011
			$share->setSharedBy($data['uid_owner']);
1012
			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
1013
1014
			$owner = $path->getOwner();
1015
			$share->setShareOwner($owner->getUID());
1016
		}
1017
1018
		if ($data['expiration'] !== null) {
1019
			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
1020
			if ($expiration !== false) {
1021
				$share->setExpirationDate($expiration);
1022
			}
1023
		}
1024
1025
		$share->setNodeId((int)$data['file_source']);
1026
		$share->setNodeType($data['item_type']);
1027
1028
		$share->setProviderId($this->identifier());
1029
1030
		return $share;
1031
	}
1032
1033
	/**
1034
	 * Get the node with file $id for $user
1035
	 *
1036
	 * @param string $userId
1037
	 * @param int $id
1038
	 * @return \OCP\Files\File|\OCP\Files\Folder
1039
	 * @throws InvalidShare
1040
	 */
1041
	private function getNode($userId, $id) {
1042
		try {
1043
			$userFolder = $this->rootFolder->getUserFolder($userId);
1044
		} catch (NoUserException $e) {
1045
			throw new InvalidShare();
1046
		}
1047
1048
		$nodes = $userFolder->getById($id);
1049
1050
		if (empty($nodes)) {
1051
			throw new InvalidShare();
1052
		}
1053
1054
		return $nodes[0];
1055
	}
1056
1057
	/**
1058
	 * A user is deleted from the system
1059
	 * So clean up the relevant shares.
1060
	 *
1061
	 * @param string $uid
1062
	 * @param int $shareType
1063
	 */
1064
	public function userDeleted($uid, $shareType) {
1065
		$qb = $this->dbConnection->getQueryBuilder();
1066
1067
		$qb->delete('share')
1068
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

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

1068
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL)))

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

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

Loading history...
1069
			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
1070
			->execute();
1071
	}
1072
1073
	/**
1074
	 * This provider does not support group shares
1075
	 *
1076
	 * @param string $gid
1077
	 */
1078
	public function groupDeleted($gid) {
1079
	}
1080
1081
	/**
1082
	 * This provider does not support group shares
1083
	 *
1084
	 * @param string $uid
1085
	 * @param string $gid
1086
	 */
1087
	public function userDeletedFromGroup($uid, $gid) {
1088
	}
1089
1090
	/**
1091
	 * get database row of a give share
1092
	 *
1093
	 * @param $id
1094
	 * @return array
1095
	 * @throws ShareNotFound
1096
	 */
1097
	protected function getRawShare($id) {
1098
1099
		// Now fetch the inserted share and create a complete share object
1100
		$qb = $this->dbConnection->getQueryBuilder();
1101
		$qb->select('*')
1102
			->from('share')
1103
			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1104
1105
		$cursor = $qb->execute();
1106
		$data = $cursor->fetch();
1107
		$cursor->closeCursor();
1108
1109
		if ($data === false) {
1110
			throw new ShareNotFound;
1111
		}
1112
1113
		return $data;
1114
	}
1115
1116
	public function getSharesInFolder($userId, Folder $node, $reshares) {
1117
		$qb = $this->dbConnection->getQueryBuilder();
1118
		$qb->select('*')
1119
			->from('share', 's')
1120
			->andWhere($qb->expr()->orX(
1121
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1122
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1123
			))
1124
			->andWhere(
1125
				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

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

1125
				$qb->expr()->eq('share_type', $qb->createNamedParameter(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL))

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

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

Loading history...
1126
			);
1127
1128
		/**
1129
		 * Reshares for this user are shares where they are the owner.
1130
		 */
1131
		if ($reshares === false) {
1132
			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1133
		} else {
1134
			$qb->andWhere(
1135
				$qb->expr()->orX(
1136
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1137
					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1138
				)
1139
			);
1140
		}
1141
1142
		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1143
		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1144
1145
		$qb->orderBy('id');
1146
1147
		$cursor = $qb->execute();
1148
		$shares = [];
1149
		while ($data = $cursor->fetch()) {
1150
			$shares[$data['fileid']][] = $this->createShareObject($data);
1151
		}
1152
		$cursor->closeCursor();
1153
1154
		return $shares;
1155
	}
1156
1157
	/**
1158
	 * @inheritdoc
1159
	 */
1160
	public function getAccessList($nodes, $currentAccess) {
1161
		$ids = [];
1162
		foreach ($nodes as $node) {
1163
			$ids[] = $node->getId();
1164
		}
1165
1166
		$qb = $this->dbConnection->getQueryBuilder();
1167
		$qb->select('share_with')
1168
			->from('share')
1169
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
0 ignored issues
show
Deprecated Code introduced by
The constant OC\Share\Constants::SHARE_TYPE_EMAIL has been deprecated: 17.0.0 - use IShare::TYPE_EMAIL instead ( Ignorable by Annotation )

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

1169
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(/** @scrutinizer ignore-deprecated */ \OCP\Share::SHARE_TYPE_EMAIL)))

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

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

Loading history...
1170
			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1171
			->andWhere($qb->expr()->orX(
1172
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1173
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1174
			))
1175
			->setMaxResults(1);
1176
		$cursor = $qb->execute();
1177
1178
		$mail = $cursor->fetch() !== false;
1179
		$cursor->closeCursor();
1180
1181
		return ['public' => $mail];
1182
	}
1183
1184
	public function getAllShares(): iterable {
1185
		$qb = $this->dbConnection->getQueryBuilder();
1186
1187
		$qb->select('*')
1188
			->from('share')
1189
			->where(
1190
				$qb->expr()->orX(
1191
					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_EMAIL))
1192
				)
1193
			);
1194
1195
		$cursor = $qb->execute();
1196
		while ($data = $cursor->fetch()) {
1197
			try {
1198
				$share = $this->createShareObject($data);
1199
			} catch (InvalidShare $e) {
1200
				continue;
1201
			} catch (ShareNotFound $e) {
1202
				continue;
1203
			}
1204
1205
			yield $share;
1206
		}
1207
		$cursor->closeCursor();
1208
	}
1209
}
1210