Passed
Push — master ( c222ba...946430 )
by John
15:06 queued 11s
created
apps/sharebymail/lib/ShareByMailProvider.php 1 patch
Indentation   +1106 added lines, -1106 removed lines patch added patch discarded remove patch
@@ -71,1117 +71,1117 @@
 block discarded – undo
71 71
  */
72 72
 class ShareByMailProvider implements IShareProvider {
73 73
 
74
-	/** @var  IDBConnection */
75
-	private $dbConnection;
76
-
77
-	/** @var ILogger */
78
-	private $logger;
79
-
80
-	/** @var ISecureRandom */
81
-	private $secureRandom;
82
-
83
-	/** @var IUserManager */
84
-	private $userManager;
85
-
86
-	/** @var IRootFolder */
87
-	private $rootFolder;
88
-
89
-	/** @var IL10N */
90
-	private $l;
91
-
92
-	/** @var IMailer */
93
-	private $mailer;
94
-
95
-	/** @var IURLGenerator */
96
-	private $urlGenerator;
97
-
98
-	/** @var IManager  */
99
-	private $activityManager;
100
-
101
-	/** @var SettingsManager */
102
-	private $settingsManager;
103
-
104
-	/** @var Defaults */
105
-	private $defaults;
106
-
107
-	/** @var IHasher */
108
-	private $hasher;
109
-
110
-	/** @var IEventDispatcher */
111
-	private $eventDispatcher;
112
-
113
-	/**
114
-	 * Return the identifier of this provider.
115
-	 *
116
-	 * @return string Containing only [a-zA-Z0-9]
117
-	 */
118
-	public function identifier() {
119
-		return 'ocMailShare';
120
-	}
121
-
122
-	public function __construct(
123
-		IDBConnection $connection,
124
-		ISecureRandom $secureRandom,
125
-		IUserManager $userManager,
126
-		IRootFolder $rootFolder,
127
-		IL10N $l,
128
-		ILogger $logger,
129
-		IMailer $mailer,
130
-		IURLGenerator $urlGenerator,
131
-		IManager $activityManager,
132
-		SettingsManager $settingsManager,
133
-		Defaults $defaults,
134
-		IHasher $hasher,
135
-		IEventDispatcher $eventDispatcher
136
-	) {
137
-		$this->dbConnection = $connection;
138
-		$this->secureRandom = $secureRandom;
139
-		$this->userManager = $userManager;
140
-		$this->rootFolder = $rootFolder;
141
-		$this->l = $l;
142
-		$this->logger = $logger;
143
-		$this->mailer = $mailer;
144
-		$this->urlGenerator = $urlGenerator;
145
-		$this->activityManager = $activityManager;
146
-		$this->settingsManager = $settingsManager;
147
-		$this->defaults = $defaults;
148
-		$this->hasher = $hasher;
149
-		$this->eventDispatcher = $eventDispatcher;
150
-	}
151
-
152
-	/**
153
-	 * Share a path
154
-	 *
155
-	 * @param IShare $share
156
-	 * @return IShare The share object
157
-	 * @throws ShareNotFound
158
-	 * @throws \Exception
159
-	 */
160
-	public function create(IShare $share) {
161
-		$shareWith = $share->getSharedWith();
162
-		/*
74
+    /** @var  IDBConnection */
75
+    private $dbConnection;
76
+
77
+    /** @var ILogger */
78
+    private $logger;
79
+
80
+    /** @var ISecureRandom */
81
+    private $secureRandom;
82
+
83
+    /** @var IUserManager */
84
+    private $userManager;
85
+
86
+    /** @var IRootFolder */
87
+    private $rootFolder;
88
+
89
+    /** @var IL10N */
90
+    private $l;
91
+
92
+    /** @var IMailer */
93
+    private $mailer;
94
+
95
+    /** @var IURLGenerator */
96
+    private $urlGenerator;
97
+
98
+    /** @var IManager  */
99
+    private $activityManager;
100
+
101
+    /** @var SettingsManager */
102
+    private $settingsManager;
103
+
104
+    /** @var Defaults */
105
+    private $defaults;
106
+
107
+    /** @var IHasher */
108
+    private $hasher;
109
+
110
+    /** @var IEventDispatcher */
111
+    private $eventDispatcher;
112
+
113
+    /**
114
+     * Return the identifier of this provider.
115
+     *
116
+     * @return string Containing only [a-zA-Z0-9]
117
+     */
118
+    public function identifier() {
119
+        return 'ocMailShare';
120
+    }
121
+
122
+    public function __construct(
123
+        IDBConnection $connection,
124
+        ISecureRandom $secureRandom,
125
+        IUserManager $userManager,
126
+        IRootFolder $rootFolder,
127
+        IL10N $l,
128
+        ILogger $logger,
129
+        IMailer $mailer,
130
+        IURLGenerator $urlGenerator,
131
+        IManager $activityManager,
132
+        SettingsManager $settingsManager,
133
+        Defaults $defaults,
134
+        IHasher $hasher,
135
+        IEventDispatcher $eventDispatcher
136
+    ) {
137
+        $this->dbConnection = $connection;
138
+        $this->secureRandom = $secureRandom;
139
+        $this->userManager = $userManager;
140
+        $this->rootFolder = $rootFolder;
141
+        $this->l = $l;
142
+        $this->logger = $logger;
143
+        $this->mailer = $mailer;
144
+        $this->urlGenerator = $urlGenerator;
145
+        $this->activityManager = $activityManager;
146
+        $this->settingsManager = $settingsManager;
147
+        $this->defaults = $defaults;
148
+        $this->hasher = $hasher;
149
+        $this->eventDispatcher = $eventDispatcher;
150
+    }
151
+
152
+    /**
153
+     * Share a path
154
+     *
155
+     * @param IShare $share
156
+     * @return IShare The share object
157
+     * @throws ShareNotFound
158
+     * @throws \Exception
159
+     */
160
+    public function create(IShare $share) {
161
+        $shareWith = $share->getSharedWith();
162
+        /*
163 163
 		 * Check if file is not already shared with the remote user
164 164
 		 */
165
-		$alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_EMAIL, $share->getNode(), 1, 0);
166
-		if (!empty($alreadyShared)) {
167
-			$message = 'Sharing %1$s failed, this item is already shared with %2$s';
168
-			$message_t = $this->l->t('Sharing %1$s failed, this item is already shared with %2$s', [$share->getNode()->getName(), $shareWith]);
169
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
170
-			throw new \Exception($message_t);
171
-		}
172
-
173
-		// if the admin enforces a password for all mail shares we create a
174
-		// random password and send it to the recipient
175
-		$password = $share->getPassword() ?: '';
176
-		$passwordEnforced = $this->settingsManager->enforcePasswordProtection();
177
-		if ($passwordEnforced && empty($password)) {
178
-			$password = $this->autoGeneratePassword($share);
179
-		}
180
-
181
-		if (!empty($password)) {
182
-			$share->setPassword($this->hasher->hash($password));
183
-		}
184
-
185
-		$shareId = $this->createMailShare($share);
186
-		$send = $this->sendPassword($share, $password);
187
-		if ($passwordEnforced && $send === false) {
188
-			$this->sendPasswordToOwner($share, $password);
189
-		}
190
-
191
-		$this->createShareActivity($share);
192
-		$data = $this->getRawShare($shareId);
193
-
194
-		return $this->createShareObject($data);
195
-	}
196
-
197
-	/**
198
-	 * auto generate password in case of password enforcement on mail shares
199
-	 *
200
-	 * @param IShare $share
201
-	 * @return string
202
-	 * @throws \Exception
203
-	 */
204
-	protected function autoGeneratePassword($share) {
205
-		$initiatorUser = $this->userManager->get($share->getSharedBy());
206
-		$initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
207
-		$allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
208
-
209
-		if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
210
-			throw new \Exception(
211
-				$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.")
212
-			);
213
-		}
214
-
215
-		$passwordEvent = new GenerateSecurePasswordEvent();
216
-		$this->eventDispatcher->dispatchTyped($passwordEvent);
217
-
218
-		$password = $passwordEvent->getPassword();
219
-		if ($password === null) {
220
-			$password = $this->secureRandom->generate(8, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS);
221
-		}
222
-
223
-		return $password;
224
-	}
225
-
226
-	/**
227
-	 * create activity if a file/folder was shared by mail
228
-	 *
229
-	 * @param IShare $share
230
-	 * @param string $type
231
-	 */
232
-	protected function createShareActivity(IShare $share, string $type = 'share') {
233
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
234
-
235
-		$this->publishActivity(
236
-			$type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_SELF : Activity::SUBJECT_UNSHARED_EMAIL_SELF,
237
-			[$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
238
-			$share->getSharedBy(),
239
-			$share->getNode()->getId(),
240
-			(string) $userFolder->getRelativePath($share->getNode()->getPath())
241
-		);
242
-
243
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
244
-			$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
245
-			$fileId = $share->getNode()->getId();
246
-			$nodes = $ownerFolder->getById($fileId);
247
-			$ownerPath = $nodes[0]->getPath();
248
-			$this->publishActivity(
249
-				$type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_BY : Activity::SUBJECT_UNSHARED_EMAIL_BY,
250
-				[$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
251
-				$share->getShareOwner(),
252
-				$fileId,
253
-				(string) $ownerFolder->getRelativePath($ownerPath)
254
-			);
255
-		}
256
-	}
257
-
258
-	/**
259
-	 * create activity if a file/folder was shared by mail
260
-	 *
261
-	 * @param IShare $share
262
-	 * @param string $sharedWith
263
-	 * @param bool $sendToSelf
264
-	 */
265
-	protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) {
266
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
267
-
268
-		if ($sendToSelf) {
269
-			$this->publishActivity(
270
-				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
271
-				[$userFolder->getRelativePath($share->getNode()->getPath())],
272
-				$share->getSharedBy(),
273
-				$share->getNode()->getId(),
274
-				(string) $userFolder->getRelativePath($share->getNode()->getPath())
275
-			);
276
-		} else {
277
-			$this->publishActivity(
278
-				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
279
-				[$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
280
-				$share->getSharedBy(),
281
-				$share->getNode()->getId(),
282
-				(string) $userFolder->getRelativePath($share->getNode()->getPath())
283
-			);
284
-		}
285
-	}
286
-
287
-
288
-	/**
289
-	 * publish activity if a file/folder was shared by mail
290
-	 *
291
-	 * @param string $subject
292
-	 * @param array $parameters
293
-	 * @param string $affectedUser
294
-	 * @param int $fileId
295
-	 * @param string $filePath
296
-	 */
297
-	protected function publishActivity(string $subject, array $parameters, string $affectedUser, int $fileId, string $filePath) {
298
-		$event = $this->activityManager->generateEvent();
299
-		$event->setApp('sharebymail')
300
-			->setType('shared')
301
-			->setSubject($subject, $parameters)
302
-			->setAffectedUser($affectedUser)
303
-			->setObject('files', $fileId, $filePath);
304
-		$this->activityManager->publish($event);
305
-	}
306
-
307
-	/**
308
-	 * @param IShare $share
309
-	 * @return int
310
-	 * @throws \Exception
311
-	 */
312
-	protected function createMailShare(IShare $share) {
313
-		$share->setToken($this->generateToken());
314
-		$shareId = $this->addShareToDB(
315
-			$share->getNodeId(),
316
-			$share->getNodeType(),
317
-			$share->getSharedWith(),
318
-			$share->getSharedBy(),
319
-			$share->getShareOwner(),
320
-			$share->getPermissions(),
321
-			$share->getToken(),
322
-			$share->getPassword(),
323
-			$share->getSendPasswordByTalk(),
324
-			$share->getHideDownload()
325
-		);
326
-
327
-		try {
328
-			$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
329
-				['token' => $share->getToken()]);
330
-			$this->sendMailNotification(
331
-				$share->getNode()->getName(),
332
-				$link,
333
-				$share->getSharedBy(),
334
-				$share->getSharedWith(),
335
-				$share->getExpirationDate()
336
-			);
337
-		} catch (HintException $hintException) {
338
-			$this->logger->logException($hintException, [
339
-				'message' => 'Failed to send share by mail.',
340
-				'level' => ILogger::ERROR,
341
-				'app' => 'sharebymail',
342
-			]);
343
-			$this->removeShareFromTable($shareId);
344
-			throw $hintException;
345
-		} catch (\Exception $e) {
346
-			$this->logger->logException($e, [
347
-				'message' => 'Failed to send share by mail.',
348
-				'level' => ILogger::ERROR,
349
-				'app' => 'sharebymail',
350
-			]);
351
-			$this->removeShareFromTable($shareId);
352
-			throw new HintException('Failed to send share by mail',
353
-				$this->l->t('Failed to send share by email'));
354
-		}
355
-
356
-		return $shareId;
357
-	}
358
-
359
-	/**
360
-	 * @param string $filename
361
-	 * @param string $link
362
-	 * @param string $initiator
363
-	 * @param string $shareWith
364
-	 * @param \DateTime|null $expiration
365
-	 * @throws \Exception If mail couldn't be sent
366
-	 */
367
-	protected function sendMailNotification($filename,
368
-											$link,
369
-											$initiator,
370
-											$shareWith,
371
-											\DateTime $expiration = null) {
372
-		$initiatorUser = $this->userManager->get($initiator);
373
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
374
-		$message = $this->mailer->createMessage();
375
-
376
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [
377
-			'filename' => $filename,
378
-			'link' => $link,
379
-			'initiator' => $initiatorDisplayName,
380
-			'expiration' => $expiration,
381
-			'shareWith' => $shareWith,
382
-		]);
383
-
384
-		$emailTemplate->setSubject($this->l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]));
385
-		$emailTemplate->addHeader();
386
-		$emailTemplate->addHeading($this->l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
387
-		$text = $this->l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
388
-
389
-		$emailTemplate->addBodyText(
390
-			htmlspecialchars($text . ' ' . $this->l->t('Click the button below to open it.')),
391
-			$text
392
-		);
393
-		$emailTemplate->addBodyButton(
394
-			$this->l->t('Open »%s«', [$filename]),
395
-			$link
396
-		);
397
-
398
-		$message->setTo([$shareWith]);
399
-
400
-		// The "From" contains the sharers name
401
-		$instanceName = $this->defaults->getName();
402
-		$senderName = $instanceName;
403
-		if ($this->settingsManager->replyToInitiator()) {
404
-			$senderName = $this->l->t(
405
-				'%1$s via %2$s',
406
-				[
407
-					$initiatorDisplayName,
408
-					$instanceName
409
-				]
410
-			);
411
-		}
412
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
413
-
414
-		// The "Reply-To" is set to the sharer if an mail address is configured
415
-		// also the default footer contains a "Do not reply" which needs to be adjusted.
416
-		$initiatorEmail = $initiatorUser->getEMailAddress();
417
-		if ($this->settingsManager->replyToInitiator() && $initiatorEmail !== null) {
418
-			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
419
-			$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
420
-		} else {
421
-			$emailTemplate->addFooter();
422
-		}
423
-
424
-		$message->useTemplate($emailTemplate);
425
-		$this->mailer->send($message);
426
-	}
427
-
428
-	/**
429
-	 * send password to recipient of a mail share
430
-	 *
431
-	 * @param IShare $share
432
-	 * @param string $password
433
-	 * @return bool
434
-	 */
435
-	protected function sendPassword(IShare $share, $password) {
436
-		$filename = $share->getNode()->getName();
437
-		$initiator = $share->getSharedBy();
438
-		$shareWith = $share->getSharedWith();
439
-
440
-		if ($password === '' || $this->settingsManager->sendPasswordByMail() === false || $share->getSendPasswordByTalk()) {
441
-			return false;
442
-		}
443
-
444
-		$initiatorUser = $this->userManager->get($initiator);
445
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
446
-		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
447
-
448
-		$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]);
449
-		$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]);
450
-
451
-		$message = $this->mailer->createMessage();
452
-
453
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [
454
-			'filename' => $filename,
455
-			'password' => $password,
456
-			'initiator' => $initiatorDisplayName,
457
-			'initiatorEmail' => $initiatorEmailAddress,
458
-			'shareWith' => $shareWith,
459
-		]);
460
-
461
-		$emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared to you by %2$s', [$filename, $initiatorDisplayName]));
462
-		$emailTemplate->addHeader();
463
-		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
464
-		$emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart);
465
-		$emailTemplate->addBodyText($this->l->t('It is protected with the following password:'));
466
-		$emailTemplate->addBodyText($password);
467
-
468
-		// The "From" contains the sharers name
469
-		$instanceName = $this->defaults->getName();
470
-		$senderName = $instanceName;
471
-		if ($this->settingsManager->replyToInitiator()) {
472
-			$senderName = $this->l->t(
473
-				'%1$s via %2$s',
474
-				[
475
-					$initiatorDisplayName,
476
-					$instanceName
477
-				]
478
-			);
479
-		}
480
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
481
-		if ($this->settingsManager->replyToInitiator() && $initiatorEmailAddress !== null) {
482
-			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
483
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
484
-		} else {
485
-			$emailTemplate->addFooter();
486
-		}
487
-
488
-		$message->setTo([$shareWith]);
489
-		$message->useTemplate($emailTemplate);
490
-		$this->mailer->send($message);
491
-
492
-		$this->createPasswordSendActivity($share, $shareWith, false);
493
-
494
-		return true;
495
-	}
496
-
497
-	protected function sendNote(IShare $share) {
498
-		$recipient = $share->getSharedWith();
499
-
500
-
501
-		$filename = $share->getNode()->getName();
502
-		$initiator = $share->getSharedBy();
503
-		$note = $share->getNote();
504
-
505
-		$initiatorUser = $this->userManager->get($initiator);
506
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
507
-		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
508
-
509
-		$plainHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
510
-		$htmlHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
511
-
512
-		$message = $this->mailer->createMessage();
513
-
514
-		$emailTemplate = $this->mailer->createEMailTemplate('shareByMail.sendNote');
515
-
516
-		$emailTemplate->setSubject($this->l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
517
-		$emailTemplate->addHeader();
518
-		$emailTemplate->addHeading(htmlspecialchars($htmlHeading), $plainHeading);
519
-		$emailTemplate->addBodyText(htmlspecialchars($note), $note);
520
-
521
-		$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
522
-			['token' => $share->getToken()]);
523
-		$emailTemplate->addBodyButton(
524
-			$this->l->t('Open »%s«', [$filename]),
525
-			$link
526
-		);
527
-
528
-		// The "From" contains the sharers name
529
-		$instanceName = $this->defaults->getName();
530
-		$senderName = $instanceName;
531
-		if ($this->settingsManager->replyToInitiator()) {
532
-			$senderName = $this->l->t(
533
-				'%1$s via %2$s',
534
-				[
535
-					$initiatorDisplayName,
536
-					$instanceName
537
-				]
538
-			);
539
-		}
540
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
541
-		if ($this->settingsManager->replyToInitiator() && $initiatorEmailAddress !== null) {
542
-			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
543
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
544
-		} else {
545
-			$emailTemplate->addFooter();
546
-		}
547
-
548
-		$message->setTo([$recipient]);
549
-		$message->useTemplate($emailTemplate);
550
-		$this->mailer->send($message);
551
-	}
552
-
553
-	/**
554
-	 * send auto generated password to the owner. This happens if the admin enforces
555
-	 * a password for mail shares and forbid to send the password by mail to the recipient
556
-	 *
557
-	 * @param IShare $share
558
-	 * @param string $password
559
-	 * @return bool
560
-	 * @throws \Exception
561
-	 */
562
-	protected function sendPasswordToOwner(IShare $share, $password) {
563
-		$filename = $share->getNode()->getName();
564
-		$initiator = $this->userManager->get($share->getSharedBy());
565
-		$initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
566
-		$initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
567
-		$shareWith = $share->getSharedWith();
568
-
569
-		if ($initiatorEMailAddress === null) {
570
-			throw new \Exception(
571
-				$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.")
572
-			);
573
-		}
574
-
575
-		$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()]);
576
-
577
-		$message = $this->mailer->createMessage();
578
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [
579
-			'filename' => $filename,
580
-			'password' => $password,
581
-			'initiator' => $initiatorDisplayName,
582
-			'initiatorEmail' => $initiatorEMailAddress,
583
-			'shareWith' => $shareWith,
584
-		]);
585
-
586
-		$emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared by you with %2$s', [$filename, $shareWith]));
587
-		$emailTemplate->addHeader();
588
-		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
589
-		$emailTemplate->addBodyText($bodyPart);
590
-		$emailTemplate->addBodyText($this->l->t('This is the password:'));
591
-		$emailTemplate->addBodyText($password);
592
-		$emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
593
-		$emailTemplate->addFooter();
594
-
595
-		$instanceName = $this->defaults->getName();
596
-		$senderName = $this->l->t(
597
-			'%1$s via %2$s',
598
-			[
599
-				$initiatorDisplayName,
600
-				$instanceName
601
-			]
602
-		);
603
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
604
-		$message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
605
-		$message->useTemplate($emailTemplate);
606
-		$this->mailer->send($message);
607
-
608
-		$this->createPasswordSendActivity($share, $shareWith, true);
609
-
610
-		return true;
611
-	}
612
-
613
-	/**
614
-	 * generate share token
615
-	 *
616
-	 * @return string
617
-	 */
618
-	protected function generateToken($size = 15) {
619
-		$token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
620
-		return $token;
621
-	}
622
-
623
-	/**
624
-	 * Get all children of this share
625
-	 *
626
-	 * @param IShare $parent
627
-	 * @return IShare[]
628
-	 */
629
-	public function getChildren(IShare $parent) {
630
-		$children = [];
631
-
632
-		$qb = $this->dbConnection->getQueryBuilder();
633
-		$qb->select('*')
634
-			->from('share')
635
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
636
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
637
-			->orderBy('id');
638
-
639
-		$cursor = $qb->execute();
640
-		while ($data = $cursor->fetch()) {
641
-			$children[] = $this->createShareObject($data);
642
-		}
643
-		$cursor->closeCursor();
644
-
645
-		return $children;
646
-	}
647
-
648
-	/**
649
-	 * add share to the database and return the ID
650
-	 *
651
-	 * @param int $itemSource
652
-	 * @param string $itemType
653
-	 * @param string $shareWith
654
-	 * @param string $sharedBy
655
-	 * @param string $uidOwner
656
-	 * @param int $permissions
657
-	 * @param string $token
658
-	 * @param string $password
659
-	 * @param bool $sendPasswordByTalk
660
-	 * @param bool $hideDownload
661
-	 * @return int
662
-	 */
663
-	protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password, $sendPasswordByTalk, $hideDownload) {
664
-		$qb = $this->dbConnection->getQueryBuilder();
665
-		$qb->insert('share')
666
-			->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
667
-			->setValue('item_type', $qb->createNamedParameter($itemType))
668
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
669
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
670
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
671
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
672
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
673
-			->setValue('permissions', $qb->createNamedParameter($permissions))
674
-			->setValue('token', $qb->createNamedParameter($token))
675
-			->setValue('password', $qb->createNamedParameter($password))
676
-			->setValue('password_by_talk', $qb->createNamedParameter($sendPasswordByTalk, IQueryBuilder::PARAM_BOOL))
677
-			->setValue('stime', $qb->createNamedParameter(time()))
678
-			->setValue('hide_download', $qb->createNamedParameter((int)$hideDownload, IQueryBuilder::PARAM_INT));
679
-
680
-		/*
165
+        $alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_EMAIL, $share->getNode(), 1, 0);
166
+        if (!empty($alreadyShared)) {
167
+            $message = 'Sharing %1$s failed, this item is already shared with %2$s';
168
+            $message_t = $this->l->t('Sharing %1$s failed, this item is already shared with %2$s', [$share->getNode()->getName(), $shareWith]);
169
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
170
+            throw new \Exception($message_t);
171
+        }
172
+
173
+        // if the admin enforces a password for all mail shares we create a
174
+        // random password and send it to the recipient
175
+        $password = $share->getPassword() ?: '';
176
+        $passwordEnforced = $this->settingsManager->enforcePasswordProtection();
177
+        if ($passwordEnforced && empty($password)) {
178
+            $password = $this->autoGeneratePassword($share);
179
+        }
180
+
181
+        if (!empty($password)) {
182
+            $share->setPassword($this->hasher->hash($password));
183
+        }
184
+
185
+        $shareId = $this->createMailShare($share);
186
+        $send = $this->sendPassword($share, $password);
187
+        if ($passwordEnforced && $send === false) {
188
+            $this->sendPasswordToOwner($share, $password);
189
+        }
190
+
191
+        $this->createShareActivity($share);
192
+        $data = $this->getRawShare($shareId);
193
+
194
+        return $this->createShareObject($data);
195
+    }
196
+
197
+    /**
198
+     * auto generate password in case of password enforcement on mail shares
199
+     *
200
+     * @param IShare $share
201
+     * @return string
202
+     * @throws \Exception
203
+     */
204
+    protected function autoGeneratePassword($share) {
205
+        $initiatorUser = $this->userManager->get($share->getSharedBy());
206
+        $initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
207
+        $allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
208
+
209
+        if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
210
+            throw new \Exception(
211
+                $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.")
212
+            );
213
+        }
214
+
215
+        $passwordEvent = new GenerateSecurePasswordEvent();
216
+        $this->eventDispatcher->dispatchTyped($passwordEvent);
217
+
218
+        $password = $passwordEvent->getPassword();
219
+        if ($password === null) {
220
+            $password = $this->secureRandom->generate(8, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS);
221
+        }
222
+
223
+        return $password;
224
+    }
225
+
226
+    /**
227
+     * create activity if a file/folder was shared by mail
228
+     *
229
+     * @param IShare $share
230
+     * @param string $type
231
+     */
232
+    protected function createShareActivity(IShare $share, string $type = 'share') {
233
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
234
+
235
+        $this->publishActivity(
236
+            $type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_SELF : Activity::SUBJECT_UNSHARED_EMAIL_SELF,
237
+            [$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
238
+            $share->getSharedBy(),
239
+            $share->getNode()->getId(),
240
+            (string) $userFolder->getRelativePath($share->getNode()->getPath())
241
+        );
242
+
243
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
244
+            $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
245
+            $fileId = $share->getNode()->getId();
246
+            $nodes = $ownerFolder->getById($fileId);
247
+            $ownerPath = $nodes[0]->getPath();
248
+            $this->publishActivity(
249
+                $type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_BY : Activity::SUBJECT_UNSHARED_EMAIL_BY,
250
+                [$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
251
+                $share->getShareOwner(),
252
+                $fileId,
253
+                (string) $ownerFolder->getRelativePath($ownerPath)
254
+            );
255
+        }
256
+    }
257
+
258
+    /**
259
+     * create activity if a file/folder was shared by mail
260
+     *
261
+     * @param IShare $share
262
+     * @param string $sharedWith
263
+     * @param bool $sendToSelf
264
+     */
265
+    protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) {
266
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
267
+
268
+        if ($sendToSelf) {
269
+            $this->publishActivity(
270
+                Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
271
+                [$userFolder->getRelativePath($share->getNode()->getPath())],
272
+                $share->getSharedBy(),
273
+                $share->getNode()->getId(),
274
+                (string) $userFolder->getRelativePath($share->getNode()->getPath())
275
+            );
276
+        } else {
277
+            $this->publishActivity(
278
+                Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
279
+                [$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
280
+                $share->getSharedBy(),
281
+                $share->getNode()->getId(),
282
+                (string) $userFolder->getRelativePath($share->getNode()->getPath())
283
+            );
284
+        }
285
+    }
286
+
287
+
288
+    /**
289
+     * publish activity if a file/folder was shared by mail
290
+     *
291
+     * @param string $subject
292
+     * @param array $parameters
293
+     * @param string $affectedUser
294
+     * @param int $fileId
295
+     * @param string $filePath
296
+     */
297
+    protected function publishActivity(string $subject, array $parameters, string $affectedUser, int $fileId, string $filePath) {
298
+        $event = $this->activityManager->generateEvent();
299
+        $event->setApp('sharebymail')
300
+            ->setType('shared')
301
+            ->setSubject($subject, $parameters)
302
+            ->setAffectedUser($affectedUser)
303
+            ->setObject('files', $fileId, $filePath);
304
+        $this->activityManager->publish($event);
305
+    }
306
+
307
+    /**
308
+     * @param IShare $share
309
+     * @return int
310
+     * @throws \Exception
311
+     */
312
+    protected function createMailShare(IShare $share) {
313
+        $share->setToken($this->generateToken());
314
+        $shareId = $this->addShareToDB(
315
+            $share->getNodeId(),
316
+            $share->getNodeType(),
317
+            $share->getSharedWith(),
318
+            $share->getSharedBy(),
319
+            $share->getShareOwner(),
320
+            $share->getPermissions(),
321
+            $share->getToken(),
322
+            $share->getPassword(),
323
+            $share->getSendPasswordByTalk(),
324
+            $share->getHideDownload()
325
+        );
326
+
327
+        try {
328
+            $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
329
+                ['token' => $share->getToken()]);
330
+            $this->sendMailNotification(
331
+                $share->getNode()->getName(),
332
+                $link,
333
+                $share->getSharedBy(),
334
+                $share->getSharedWith(),
335
+                $share->getExpirationDate()
336
+            );
337
+        } catch (HintException $hintException) {
338
+            $this->logger->logException($hintException, [
339
+                'message' => 'Failed to send share by mail.',
340
+                'level' => ILogger::ERROR,
341
+                'app' => 'sharebymail',
342
+            ]);
343
+            $this->removeShareFromTable($shareId);
344
+            throw $hintException;
345
+        } catch (\Exception $e) {
346
+            $this->logger->logException($e, [
347
+                'message' => 'Failed to send share by mail.',
348
+                'level' => ILogger::ERROR,
349
+                'app' => 'sharebymail',
350
+            ]);
351
+            $this->removeShareFromTable($shareId);
352
+            throw new HintException('Failed to send share by mail',
353
+                $this->l->t('Failed to send share by email'));
354
+        }
355
+
356
+        return $shareId;
357
+    }
358
+
359
+    /**
360
+     * @param string $filename
361
+     * @param string $link
362
+     * @param string $initiator
363
+     * @param string $shareWith
364
+     * @param \DateTime|null $expiration
365
+     * @throws \Exception If mail couldn't be sent
366
+     */
367
+    protected function sendMailNotification($filename,
368
+                                            $link,
369
+                                            $initiator,
370
+                                            $shareWith,
371
+                                            \DateTime $expiration = null) {
372
+        $initiatorUser = $this->userManager->get($initiator);
373
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
374
+        $message = $this->mailer->createMessage();
375
+
376
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [
377
+            'filename' => $filename,
378
+            'link' => $link,
379
+            'initiator' => $initiatorDisplayName,
380
+            'expiration' => $expiration,
381
+            'shareWith' => $shareWith,
382
+        ]);
383
+
384
+        $emailTemplate->setSubject($this->l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]));
385
+        $emailTemplate->addHeader();
386
+        $emailTemplate->addHeading($this->l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
387
+        $text = $this->l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
388
+
389
+        $emailTemplate->addBodyText(
390
+            htmlspecialchars($text . ' ' . $this->l->t('Click the button below to open it.')),
391
+            $text
392
+        );
393
+        $emailTemplate->addBodyButton(
394
+            $this->l->t('Open »%s«', [$filename]),
395
+            $link
396
+        );
397
+
398
+        $message->setTo([$shareWith]);
399
+
400
+        // The "From" contains the sharers name
401
+        $instanceName = $this->defaults->getName();
402
+        $senderName = $instanceName;
403
+        if ($this->settingsManager->replyToInitiator()) {
404
+            $senderName = $this->l->t(
405
+                '%1$s via %2$s',
406
+                [
407
+                    $initiatorDisplayName,
408
+                    $instanceName
409
+                ]
410
+            );
411
+        }
412
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
413
+
414
+        // The "Reply-To" is set to the sharer if an mail address is configured
415
+        // also the default footer contains a "Do not reply" which needs to be adjusted.
416
+        $initiatorEmail = $initiatorUser->getEMailAddress();
417
+        if ($this->settingsManager->replyToInitiator() && $initiatorEmail !== null) {
418
+            $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
419
+            $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
420
+        } else {
421
+            $emailTemplate->addFooter();
422
+        }
423
+
424
+        $message->useTemplate($emailTemplate);
425
+        $this->mailer->send($message);
426
+    }
427
+
428
+    /**
429
+     * send password to recipient of a mail share
430
+     *
431
+     * @param IShare $share
432
+     * @param string $password
433
+     * @return bool
434
+     */
435
+    protected function sendPassword(IShare $share, $password) {
436
+        $filename = $share->getNode()->getName();
437
+        $initiator = $share->getSharedBy();
438
+        $shareWith = $share->getSharedWith();
439
+
440
+        if ($password === '' || $this->settingsManager->sendPasswordByMail() === false || $share->getSendPasswordByTalk()) {
441
+            return false;
442
+        }
443
+
444
+        $initiatorUser = $this->userManager->get($initiator);
445
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
446
+        $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
447
+
448
+        $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]);
449
+        $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]);
450
+
451
+        $message = $this->mailer->createMessage();
452
+
453
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [
454
+            'filename' => $filename,
455
+            'password' => $password,
456
+            'initiator' => $initiatorDisplayName,
457
+            'initiatorEmail' => $initiatorEmailAddress,
458
+            'shareWith' => $shareWith,
459
+        ]);
460
+
461
+        $emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared to you by %2$s', [$filename, $initiatorDisplayName]));
462
+        $emailTemplate->addHeader();
463
+        $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
464
+        $emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart);
465
+        $emailTemplate->addBodyText($this->l->t('It is protected with the following password:'));
466
+        $emailTemplate->addBodyText($password);
467
+
468
+        // The "From" contains the sharers name
469
+        $instanceName = $this->defaults->getName();
470
+        $senderName = $instanceName;
471
+        if ($this->settingsManager->replyToInitiator()) {
472
+            $senderName = $this->l->t(
473
+                '%1$s via %2$s',
474
+                [
475
+                    $initiatorDisplayName,
476
+                    $instanceName
477
+                ]
478
+            );
479
+        }
480
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
481
+        if ($this->settingsManager->replyToInitiator() && $initiatorEmailAddress !== null) {
482
+            $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
483
+            $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
484
+        } else {
485
+            $emailTemplate->addFooter();
486
+        }
487
+
488
+        $message->setTo([$shareWith]);
489
+        $message->useTemplate($emailTemplate);
490
+        $this->mailer->send($message);
491
+
492
+        $this->createPasswordSendActivity($share, $shareWith, false);
493
+
494
+        return true;
495
+    }
496
+
497
+    protected function sendNote(IShare $share) {
498
+        $recipient = $share->getSharedWith();
499
+
500
+
501
+        $filename = $share->getNode()->getName();
502
+        $initiator = $share->getSharedBy();
503
+        $note = $share->getNote();
504
+
505
+        $initiatorUser = $this->userManager->get($initiator);
506
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
507
+        $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
508
+
509
+        $plainHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
510
+        $htmlHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
511
+
512
+        $message = $this->mailer->createMessage();
513
+
514
+        $emailTemplate = $this->mailer->createEMailTemplate('shareByMail.sendNote');
515
+
516
+        $emailTemplate->setSubject($this->l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
517
+        $emailTemplate->addHeader();
518
+        $emailTemplate->addHeading(htmlspecialchars($htmlHeading), $plainHeading);
519
+        $emailTemplate->addBodyText(htmlspecialchars($note), $note);
520
+
521
+        $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
522
+            ['token' => $share->getToken()]);
523
+        $emailTemplate->addBodyButton(
524
+            $this->l->t('Open »%s«', [$filename]),
525
+            $link
526
+        );
527
+
528
+        // The "From" contains the sharers name
529
+        $instanceName = $this->defaults->getName();
530
+        $senderName = $instanceName;
531
+        if ($this->settingsManager->replyToInitiator()) {
532
+            $senderName = $this->l->t(
533
+                '%1$s via %2$s',
534
+                [
535
+                    $initiatorDisplayName,
536
+                    $instanceName
537
+                ]
538
+            );
539
+        }
540
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
541
+        if ($this->settingsManager->replyToInitiator() && $initiatorEmailAddress !== null) {
542
+            $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
543
+            $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
544
+        } else {
545
+            $emailTemplate->addFooter();
546
+        }
547
+
548
+        $message->setTo([$recipient]);
549
+        $message->useTemplate($emailTemplate);
550
+        $this->mailer->send($message);
551
+    }
552
+
553
+    /**
554
+     * send auto generated password to the owner. This happens if the admin enforces
555
+     * a password for mail shares and forbid to send the password by mail to the recipient
556
+     *
557
+     * @param IShare $share
558
+     * @param string $password
559
+     * @return bool
560
+     * @throws \Exception
561
+     */
562
+    protected function sendPasswordToOwner(IShare $share, $password) {
563
+        $filename = $share->getNode()->getName();
564
+        $initiator = $this->userManager->get($share->getSharedBy());
565
+        $initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
566
+        $initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
567
+        $shareWith = $share->getSharedWith();
568
+
569
+        if ($initiatorEMailAddress === null) {
570
+            throw new \Exception(
571
+                $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.")
572
+            );
573
+        }
574
+
575
+        $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()]);
576
+
577
+        $message = $this->mailer->createMessage();
578
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [
579
+            'filename' => $filename,
580
+            'password' => $password,
581
+            'initiator' => $initiatorDisplayName,
582
+            'initiatorEmail' => $initiatorEMailAddress,
583
+            'shareWith' => $shareWith,
584
+        ]);
585
+
586
+        $emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared by you with %2$s', [$filename, $shareWith]));
587
+        $emailTemplate->addHeader();
588
+        $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
589
+        $emailTemplate->addBodyText($bodyPart);
590
+        $emailTemplate->addBodyText($this->l->t('This is the password:'));
591
+        $emailTemplate->addBodyText($password);
592
+        $emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
593
+        $emailTemplate->addFooter();
594
+
595
+        $instanceName = $this->defaults->getName();
596
+        $senderName = $this->l->t(
597
+            '%1$s via %2$s',
598
+            [
599
+                $initiatorDisplayName,
600
+                $instanceName
601
+            ]
602
+        );
603
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
604
+        $message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
605
+        $message->useTemplate($emailTemplate);
606
+        $this->mailer->send($message);
607
+
608
+        $this->createPasswordSendActivity($share, $shareWith, true);
609
+
610
+        return true;
611
+    }
612
+
613
+    /**
614
+     * generate share token
615
+     *
616
+     * @return string
617
+     */
618
+    protected function generateToken($size = 15) {
619
+        $token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
620
+        return $token;
621
+    }
622
+
623
+    /**
624
+     * Get all children of this share
625
+     *
626
+     * @param IShare $parent
627
+     * @return IShare[]
628
+     */
629
+    public function getChildren(IShare $parent) {
630
+        $children = [];
631
+
632
+        $qb = $this->dbConnection->getQueryBuilder();
633
+        $qb->select('*')
634
+            ->from('share')
635
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
636
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
637
+            ->orderBy('id');
638
+
639
+        $cursor = $qb->execute();
640
+        while ($data = $cursor->fetch()) {
641
+            $children[] = $this->createShareObject($data);
642
+        }
643
+        $cursor->closeCursor();
644
+
645
+        return $children;
646
+    }
647
+
648
+    /**
649
+     * add share to the database and return the ID
650
+     *
651
+     * @param int $itemSource
652
+     * @param string $itemType
653
+     * @param string $shareWith
654
+     * @param string $sharedBy
655
+     * @param string $uidOwner
656
+     * @param int $permissions
657
+     * @param string $token
658
+     * @param string $password
659
+     * @param bool $sendPasswordByTalk
660
+     * @param bool $hideDownload
661
+     * @return int
662
+     */
663
+    protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password, $sendPasswordByTalk, $hideDownload) {
664
+        $qb = $this->dbConnection->getQueryBuilder();
665
+        $qb->insert('share')
666
+            ->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
667
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
668
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
669
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
670
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
671
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
672
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
673
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
674
+            ->setValue('token', $qb->createNamedParameter($token))
675
+            ->setValue('password', $qb->createNamedParameter($password))
676
+            ->setValue('password_by_talk', $qb->createNamedParameter($sendPasswordByTalk, IQueryBuilder::PARAM_BOOL))
677
+            ->setValue('stime', $qb->createNamedParameter(time()))
678
+            ->setValue('hide_download', $qb->createNamedParameter((int)$hideDownload, IQueryBuilder::PARAM_INT));
679
+
680
+        /*
681 681
 		 * Added to fix https://github.com/owncloud/core/issues/22215
682 682
 		 * Can be removed once we get rid of ajax/share.php
683 683
 		 */
684
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
685
-
686
-		$qb->execute();
687
-		$id = $qb->getLastInsertId();
688
-
689
-		return (int)$id;
690
-	}
691
-
692
-	/**
693
-	 * Update a share
694
-	 *
695
-	 * @param IShare $share
696
-	 * @param string|null $plainTextPassword
697
-	 * @return IShare The share object
698
-	 */
699
-	public function update(IShare $share, $plainTextPassword = null) {
700
-		$originalShare = $this->getShareById($share->getId());
701
-
702
-		// a real password was given
703
-		$validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
704
-
705
-		if ($validPassword && ($originalShare->getPassword() !== $share->getPassword() ||
706
-								($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()))) {
707
-			$this->sendPassword($share, $plainTextPassword);
708
-		}
709
-		/*
684
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
685
+
686
+        $qb->execute();
687
+        $id = $qb->getLastInsertId();
688
+
689
+        return (int)$id;
690
+    }
691
+
692
+    /**
693
+     * Update a share
694
+     *
695
+     * @param IShare $share
696
+     * @param string|null $plainTextPassword
697
+     * @return IShare The share object
698
+     */
699
+    public function update(IShare $share, $plainTextPassword = null) {
700
+        $originalShare = $this->getShareById($share->getId());
701
+
702
+        // a real password was given
703
+        $validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
704
+
705
+        if ($validPassword && ($originalShare->getPassword() !== $share->getPassword() ||
706
+                                ($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()))) {
707
+            $this->sendPassword($share, $plainTextPassword);
708
+        }
709
+        /*
710 710
 		 * We allow updating the permissions and password of mail shares
711 711
 		 */
712
-		$qb = $this->dbConnection->getQueryBuilder();
713
-		$qb->update('share')
714
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
715
-			->set('permissions', $qb->createNamedParameter($share->getPermissions()))
716
-			->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
717
-			->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
718
-			->set('password', $qb->createNamedParameter($share->getPassword()))
719
-			->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
720
-			->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
721
-			->set('note', $qb->createNamedParameter($share->getNote()))
722
-			->set('hide_download', $qb->createNamedParameter((int)$share->getHideDownload(), IQueryBuilder::PARAM_INT))
723
-			->execute();
724
-
725
-		if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
726
-			$this->sendNote($share);
727
-		}
728
-
729
-		return $share;
730
-	}
731
-
732
-	/**
733
-	 * @inheritdoc
734
-	 */
735
-	public function move(IShare $share, $recipient) {
736
-		/**
737
-		 * nothing to do here, mail shares are only outgoing shares
738
-		 */
739
-		return $share;
740
-	}
741
-
742
-	/**
743
-	 * Delete a share (owner unShares the file)
744
-	 *
745
-	 * @param IShare $share
746
-	 */
747
-	public function delete(IShare $share) {
748
-		try {
749
-			$this->createShareActivity($share, 'unshare');
750
-		} catch (\Exception $e) {
751
-		}
752
-
753
-		$this->removeShareFromTable($share->getId());
754
-	}
755
-
756
-	/**
757
-	 * @inheritdoc
758
-	 */
759
-	public function deleteFromSelf(IShare $share, $recipient) {
760
-		// nothing to do here, mail shares are only outgoing shares
761
-	}
762
-
763
-	public function restore(IShare $share, string $recipient): IShare {
764
-		throw new GenericShareException('not implemented');
765
-	}
766
-
767
-	/**
768
-	 * @inheritdoc
769
-	 */
770
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
771
-		$qb = $this->dbConnection->getQueryBuilder();
772
-		$qb->select('*')
773
-			->from('share');
774
-
775
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
776
-
777
-		/**
778
-		 * Reshares for this user are shares where they are the owner.
779
-		 */
780
-		if ($reshares === false) {
781
-			//Special case for old shares created via the web UI
782
-			$or1 = $qb->expr()->andX(
783
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
784
-				$qb->expr()->isNull('uid_initiator')
785
-			);
786
-
787
-			$qb->andWhere(
788
-				$qb->expr()->orX(
789
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
790
-					$or1
791
-				)
792
-			);
793
-		} else {
794
-			$qb->andWhere(
795
-				$qb->expr()->orX(
796
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
797
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
798
-				)
799
-			);
800
-		}
801
-
802
-		if ($node !== null) {
803
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
804
-		}
805
-
806
-		if ($limit !== -1) {
807
-			$qb->setMaxResults($limit);
808
-		}
809
-
810
-		$qb->setFirstResult($offset);
811
-		$qb->orderBy('id');
812
-
813
-		$cursor = $qb->execute();
814
-		$shares = [];
815
-		while ($data = $cursor->fetch()) {
816
-			$shares[] = $this->createShareObject($data);
817
-		}
818
-		$cursor->closeCursor();
819
-
820
-		return $shares;
821
-	}
822
-
823
-	/**
824
-	 * @inheritdoc
825
-	 */
826
-	public function getShareById($id, $recipientId = null) {
827
-		$qb = $this->dbConnection->getQueryBuilder();
828
-
829
-		$qb->select('*')
830
-			->from('share')
831
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
832
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
833
-
834
-		$cursor = $qb->execute();
835
-		$data = $cursor->fetch();
836
-		$cursor->closeCursor();
837
-
838
-		if ($data === false) {
839
-			throw new ShareNotFound();
840
-		}
841
-
842
-		try {
843
-			$share = $this->createShareObject($data);
844
-		} catch (InvalidShare $e) {
845
-			throw new ShareNotFound();
846
-		}
847
-
848
-		return $share;
849
-	}
850
-
851
-	/**
852
-	 * Get shares for a given path
853
-	 *
854
-	 * @param \OCP\Files\Node $path
855
-	 * @return IShare[]
856
-	 */
857
-	public function getSharesByPath(Node $path) {
858
-		$qb = $this->dbConnection->getQueryBuilder();
859
-
860
-		$cursor = $qb->select('*')
861
-			->from('share')
862
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
863
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
864
-			->execute();
865
-
866
-		$shares = [];
867
-		while ($data = $cursor->fetch()) {
868
-			$shares[] = $this->createShareObject($data);
869
-		}
870
-		$cursor->closeCursor();
871
-
872
-		return $shares;
873
-	}
874
-
875
-	/**
876
-	 * @inheritdoc
877
-	 */
878
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
879
-		/** @var IShare[] $shares */
880
-		$shares = [];
881
-
882
-		//Get shares directly with this user
883
-		$qb = $this->dbConnection->getQueryBuilder();
884
-		$qb->select('*')
885
-			->from('share');
886
-
887
-		// Order by id
888
-		$qb->orderBy('id');
889
-
890
-		// Set limit and offset
891
-		if ($limit !== -1) {
892
-			$qb->setMaxResults($limit);
893
-		}
894
-		$qb->setFirstResult($offset);
895
-
896
-		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
897
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
898
-
899
-		// Filter by node if provided
900
-		if ($node !== null) {
901
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
902
-		}
903
-
904
-		$cursor = $qb->execute();
905
-
906
-		while ($data = $cursor->fetch()) {
907
-			$shares[] = $this->createShareObject($data);
908
-		}
909
-		$cursor->closeCursor();
910
-
911
-
912
-		return $shares;
913
-	}
914
-
915
-	/**
916
-	 * Get a share by token
917
-	 *
918
-	 * @param string $token
919
-	 * @return IShare
920
-	 * @throws ShareNotFound
921
-	 */
922
-	public function getShareByToken($token) {
923
-		$qb = $this->dbConnection->getQueryBuilder();
924
-
925
-		$cursor = $qb->select('*')
926
-			->from('share')
927
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
928
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
929
-			->execute();
930
-
931
-		$data = $cursor->fetch();
932
-
933
-		if ($data === false) {
934
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
935
-		}
936
-
937
-		try {
938
-			$share = $this->createShareObject($data);
939
-		} catch (InvalidShare $e) {
940
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
941
-		}
942
-
943
-		return $share;
944
-	}
945
-
946
-	/**
947
-	 * remove share from table
948
-	 *
949
-	 * @param string $shareId
950
-	 */
951
-	protected function removeShareFromTable($shareId) {
952
-		$qb = $this->dbConnection->getQueryBuilder();
953
-		$qb->delete('share')
954
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
955
-		$qb->execute();
956
-	}
957
-
958
-	/**
959
-	 * Create a share object from an database row
960
-	 *
961
-	 * @param array $data
962
-	 * @return IShare
963
-	 * @throws InvalidShare
964
-	 * @throws ShareNotFound
965
-	 */
966
-	protected function createShareObject($data) {
967
-		$share = new Share($this->rootFolder, $this->userManager);
968
-		$share->setId((int)$data['id'])
969
-			->setShareType((int)$data['share_type'])
970
-			->setPermissions((int)$data['permissions'])
971
-			->setTarget($data['file_target'])
972
-			->setMailSend((bool)$data['mail_send'])
973
-			->setNote($data['note'])
974
-			->setToken($data['token']);
975
-
976
-		$shareTime = new \DateTime();
977
-		$shareTime->setTimestamp((int)$data['stime']);
978
-		$share->setShareTime($shareTime);
979
-		$share->setSharedWith($data['share_with']);
980
-		$share->setPassword($data['password']);
981
-		$share->setSendPasswordByTalk((bool)$data['password_by_talk']);
982
-		$share->setHideDownload((bool)$data['hide_download']);
983
-
984
-		if ($data['uid_initiator'] !== null) {
985
-			$share->setShareOwner($data['uid_owner']);
986
-			$share->setSharedBy($data['uid_initiator']);
987
-		} else {
988
-			//OLD SHARE
989
-			$share->setSharedBy($data['uid_owner']);
990
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
991
-
992
-			$owner = $path->getOwner();
993
-			$share->setShareOwner($owner->getUID());
994
-		}
995
-
996
-		if ($data['expiration'] !== null) {
997
-			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
998
-			if ($expiration !== false) {
999
-				$share->setExpirationDate($expiration);
1000
-			}
1001
-		}
1002
-
1003
-		$share->setNodeId((int)$data['file_source']);
1004
-		$share->setNodeType($data['item_type']);
1005
-
1006
-		$share->setProviderId($this->identifier());
1007
-
1008
-		return $share;
1009
-	}
1010
-
1011
-	/**
1012
-	 * Get the node with file $id for $user
1013
-	 *
1014
-	 * @param string $userId
1015
-	 * @param int $id
1016
-	 * @return \OCP\Files\File|\OCP\Files\Folder
1017
-	 * @throws InvalidShare
1018
-	 */
1019
-	private function getNode($userId, $id) {
1020
-		try {
1021
-			$userFolder = $this->rootFolder->getUserFolder($userId);
1022
-		} catch (NoUserException $e) {
1023
-			throw new InvalidShare();
1024
-		}
1025
-
1026
-		$nodes = $userFolder->getById($id);
1027
-
1028
-		if (empty($nodes)) {
1029
-			throw new InvalidShare();
1030
-		}
1031
-
1032
-		return $nodes[0];
1033
-	}
1034
-
1035
-	/**
1036
-	 * A user is deleted from the system
1037
-	 * So clean up the relevant shares.
1038
-	 *
1039
-	 * @param string $uid
1040
-	 * @param int $shareType
1041
-	 */
1042
-	public function userDeleted($uid, $shareType) {
1043
-		$qb = $this->dbConnection->getQueryBuilder();
1044
-
1045
-		$qb->delete('share')
1046
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
1047
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
1048
-			->execute();
1049
-	}
1050
-
1051
-	/**
1052
-	 * This provider does not support group shares
1053
-	 *
1054
-	 * @param string $gid
1055
-	 */
1056
-	public function groupDeleted($gid) {
1057
-	}
1058
-
1059
-	/**
1060
-	 * This provider does not support group shares
1061
-	 *
1062
-	 * @param string $uid
1063
-	 * @param string $gid
1064
-	 */
1065
-	public function userDeletedFromGroup($uid, $gid) {
1066
-	}
1067
-
1068
-	/**
1069
-	 * get database row of a give share
1070
-	 *
1071
-	 * @param $id
1072
-	 * @return array
1073
-	 * @throws ShareNotFound
1074
-	 */
1075
-	protected function getRawShare($id) {
1076
-
1077
-		// Now fetch the inserted share and create a complete share object
1078
-		$qb = $this->dbConnection->getQueryBuilder();
1079
-		$qb->select('*')
1080
-			->from('share')
1081
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1082
-
1083
-		$cursor = $qb->execute();
1084
-		$data = $cursor->fetch();
1085
-		$cursor->closeCursor();
1086
-
1087
-		if ($data === false) {
1088
-			throw new ShareNotFound;
1089
-		}
1090
-
1091
-		return $data;
1092
-	}
1093
-
1094
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
1095
-		$qb = $this->dbConnection->getQueryBuilder();
1096
-		$qb->select('*')
1097
-			->from('share', 's')
1098
-			->andWhere($qb->expr()->orX(
1099
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1100
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1101
-			))
1102
-			->andWhere(
1103
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
1104
-			);
1105
-
1106
-		/**
1107
-		 * Reshares for this user are shares where they are the owner.
1108
-		 */
1109
-		if ($reshares === false) {
1110
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1111
-		} else {
1112
-			$qb->andWhere(
1113
-				$qb->expr()->orX(
1114
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1115
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1116
-				)
1117
-			);
1118
-		}
1119
-
1120
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1121
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1122
-
1123
-		$qb->orderBy('id');
1124
-
1125
-		$cursor = $qb->execute();
1126
-		$shares = [];
1127
-		while ($data = $cursor->fetch()) {
1128
-			$shares[$data['fileid']][] = $this->createShareObject($data);
1129
-		}
1130
-		$cursor->closeCursor();
1131
-
1132
-		return $shares;
1133
-	}
1134
-
1135
-	/**
1136
-	 * @inheritdoc
1137
-	 */
1138
-	public function getAccessList($nodes, $currentAccess) {
1139
-		$ids = [];
1140
-		foreach ($nodes as $node) {
1141
-			$ids[] = $node->getId();
1142
-		}
1143
-
1144
-		$qb = $this->dbConnection->getQueryBuilder();
1145
-		$qb->select('share_with')
1146
-			->from('share')
1147
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
1148
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1149
-			->andWhere($qb->expr()->orX(
1150
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1151
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1152
-			))
1153
-			->setMaxResults(1);
1154
-		$cursor = $qb->execute();
1155
-
1156
-		$mail = $cursor->fetch() !== false;
1157
-		$cursor->closeCursor();
1158
-
1159
-		return ['public' => $mail];
1160
-	}
1161
-
1162
-	public function getAllShares(): iterable {
1163
-		$qb = $this->dbConnection->getQueryBuilder();
1164
-
1165
-		$qb->select('*')
1166
-			->from('share')
1167
-			->where(
1168
-				$qb->expr()->orX(
1169
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_EMAIL))
1170
-				)
1171
-			);
1172
-
1173
-		$cursor = $qb->execute();
1174
-		while ($data = $cursor->fetch()) {
1175
-			try {
1176
-				$share = $this->createShareObject($data);
1177
-			} catch (InvalidShare $e) {
1178
-				continue;
1179
-			} catch (ShareNotFound $e) {
1180
-				continue;
1181
-			}
1182
-
1183
-			yield $share;
1184
-		}
1185
-		$cursor->closeCursor();
1186
-	}
712
+        $qb = $this->dbConnection->getQueryBuilder();
713
+        $qb->update('share')
714
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
715
+            ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
716
+            ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
717
+            ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
718
+            ->set('password', $qb->createNamedParameter($share->getPassword()))
719
+            ->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
720
+            ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
721
+            ->set('note', $qb->createNamedParameter($share->getNote()))
722
+            ->set('hide_download', $qb->createNamedParameter((int)$share->getHideDownload(), IQueryBuilder::PARAM_INT))
723
+            ->execute();
724
+
725
+        if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
726
+            $this->sendNote($share);
727
+        }
728
+
729
+        return $share;
730
+    }
731
+
732
+    /**
733
+     * @inheritdoc
734
+     */
735
+    public function move(IShare $share, $recipient) {
736
+        /**
737
+         * nothing to do here, mail shares are only outgoing shares
738
+         */
739
+        return $share;
740
+    }
741
+
742
+    /**
743
+     * Delete a share (owner unShares the file)
744
+     *
745
+     * @param IShare $share
746
+     */
747
+    public function delete(IShare $share) {
748
+        try {
749
+            $this->createShareActivity($share, 'unshare');
750
+        } catch (\Exception $e) {
751
+        }
752
+
753
+        $this->removeShareFromTable($share->getId());
754
+    }
755
+
756
+    /**
757
+     * @inheritdoc
758
+     */
759
+    public function deleteFromSelf(IShare $share, $recipient) {
760
+        // nothing to do here, mail shares are only outgoing shares
761
+    }
762
+
763
+    public function restore(IShare $share, string $recipient): IShare {
764
+        throw new GenericShareException('not implemented');
765
+    }
766
+
767
+    /**
768
+     * @inheritdoc
769
+     */
770
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
771
+        $qb = $this->dbConnection->getQueryBuilder();
772
+        $qb->select('*')
773
+            ->from('share');
774
+
775
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
776
+
777
+        /**
778
+         * Reshares for this user are shares where they are the owner.
779
+         */
780
+        if ($reshares === false) {
781
+            //Special case for old shares created via the web UI
782
+            $or1 = $qb->expr()->andX(
783
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
784
+                $qb->expr()->isNull('uid_initiator')
785
+            );
786
+
787
+            $qb->andWhere(
788
+                $qb->expr()->orX(
789
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
790
+                    $or1
791
+                )
792
+            );
793
+        } else {
794
+            $qb->andWhere(
795
+                $qb->expr()->orX(
796
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
797
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
798
+                )
799
+            );
800
+        }
801
+
802
+        if ($node !== null) {
803
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
804
+        }
805
+
806
+        if ($limit !== -1) {
807
+            $qb->setMaxResults($limit);
808
+        }
809
+
810
+        $qb->setFirstResult($offset);
811
+        $qb->orderBy('id');
812
+
813
+        $cursor = $qb->execute();
814
+        $shares = [];
815
+        while ($data = $cursor->fetch()) {
816
+            $shares[] = $this->createShareObject($data);
817
+        }
818
+        $cursor->closeCursor();
819
+
820
+        return $shares;
821
+    }
822
+
823
+    /**
824
+     * @inheritdoc
825
+     */
826
+    public function getShareById($id, $recipientId = null) {
827
+        $qb = $this->dbConnection->getQueryBuilder();
828
+
829
+        $qb->select('*')
830
+            ->from('share')
831
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
832
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
833
+
834
+        $cursor = $qb->execute();
835
+        $data = $cursor->fetch();
836
+        $cursor->closeCursor();
837
+
838
+        if ($data === false) {
839
+            throw new ShareNotFound();
840
+        }
841
+
842
+        try {
843
+            $share = $this->createShareObject($data);
844
+        } catch (InvalidShare $e) {
845
+            throw new ShareNotFound();
846
+        }
847
+
848
+        return $share;
849
+    }
850
+
851
+    /**
852
+     * Get shares for a given path
853
+     *
854
+     * @param \OCP\Files\Node $path
855
+     * @return IShare[]
856
+     */
857
+    public function getSharesByPath(Node $path) {
858
+        $qb = $this->dbConnection->getQueryBuilder();
859
+
860
+        $cursor = $qb->select('*')
861
+            ->from('share')
862
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
863
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
864
+            ->execute();
865
+
866
+        $shares = [];
867
+        while ($data = $cursor->fetch()) {
868
+            $shares[] = $this->createShareObject($data);
869
+        }
870
+        $cursor->closeCursor();
871
+
872
+        return $shares;
873
+    }
874
+
875
+    /**
876
+     * @inheritdoc
877
+     */
878
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
879
+        /** @var IShare[] $shares */
880
+        $shares = [];
881
+
882
+        //Get shares directly with this user
883
+        $qb = $this->dbConnection->getQueryBuilder();
884
+        $qb->select('*')
885
+            ->from('share');
886
+
887
+        // Order by id
888
+        $qb->orderBy('id');
889
+
890
+        // Set limit and offset
891
+        if ($limit !== -1) {
892
+            $qb->setMaxResults($limit);
893
+        }
894
+        $qb->setFirstResult($offset);
895
+
896
+        $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
897
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
898
+
899
+        // Filter by node if provided
900
+        if ($node !== null) {
901
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
902
+        }
903
+
904
+        $cursor = $qb->execute();
905
+
906
+        while ($data = $cursor->fetch()) {
907
+            $shares[] = $this->createShareObject($data);
908
+        }
909
+        $cursor->closeCursor();
910
+
911
+
912
+        return $shares;
913
+    }
914
+
915
+    /**
916
+     * Get a share by token
917
+     *
918
+     * @param string $token
919
+     * @return IShare
920
+     * @throws ShareNotFound
921
+     */
922
+    public function getShareByToken($token) {
923
+        $qb = $this->dbConnection->getQueryBuilder();
924
+
925
+        $cursor = $qb->select('*')
926
+            ->from('share')
927
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
928
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
929
+            ->execute();
930
+
931
+        $data = $cursor->fetch();
932
+
933
+        if ($data === false) {
934
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
935
+        }
936
+
937
+        try {
938
+            $share = $this->createShareObject($data);
939
+        } catch (InvalidShare $e) {
940
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
941
+        }
942
+
943
+        return $share;
944
+    }
945
+
946
+    /**
947
+     * remove share from table
948
+     *
949
+     * @param string $shareId
950
+     */
951
+    protected function removeShareFromTable($shareId) {
952
+        $qb = $this->dbConnection->getQueryBuilder();
953
+        $qb->delete('share')
954
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
955
+        $qb->execute();
956
+    }
957
+
958
+    /**
959
+     * Create a share object from an database row
960
+     *
961
+     * @param array $data
962
+     * @return IShare
963
+     * @throws InvalidShare
964
+     * @throws ShareNotFound
965
+     */
966
+    protected function createShareObject($data) {
967
+        $share = new Share($this->rootFolder, $this->userManager);
968
+        $share->setId((int)$data['id'])
969
+            ->setShareType((int)$data['share_type'])
970
+            ->setPermissions((int)$data['permissions'])
971
+            ->setTarget($data['file_target'])
972
+            ->setMailSend((bool)$data['mail_send'])
973
+            ->setNote($data['note'])
974
+            ->setToken($data['token']);
975
+
976
+        $shareTime = new \DateTime();
977
+        $shareTime->setTimestamp((int)$data['stime']);
978
+        $share->setShareTime($shareTime);
979
+        $share->setSharedWith($data['share_with']);
980
+        $share->setPassword($data['password']);
981
+        $share->setSendPasswordByTalk((bool)$data['password_by_talk']);
982
+        $share->setHideDownload((bool)$data['hide_download']);
983
+
984
+        if ($data['uid_initiator'] !== null) {
985
+            $share->setShareOwner($data['uid_owner']);
986
+            $share->setSharedBy($data['uid_initiator']);
987
+        } else {
988
+            //OLD SHARE
989
+            $share->setSharedBy($data['uid_owner']);
990
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
991
+
992
+            $owner = $path->getOwner();
993
+            $share->setShareOwner($owner->getUID());
994
+        }
995
+
996
+        if ($data['expiration'] !== null) {
997
+            $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
998
+            if ($expiration !== false) {
999
+                $share->setExpirationDate($expiration);
1000
+            }
1001
+        }
1002
+
1003
+        $share->setNodeId((int)$data['file_source']);
1004
+        $share->setNodeType($data['item_type']);
1005
+
1006
+        $share->setProviderId($this->identifier());
1007
+
1008
+        return $share;
1009
+    }
1010
+
1011
+    /**
1012
+     * Get the node with file $id for $user
1013
+     *
1014
+     * @param string $userId
1015
+     * @param int $id
1016
+     * @return \OCP\Files\File|\OCP\Files\Folder
1017
+     * @throws InvalidShare
1018
+     */
1019
+    private function getNode($userId, $id) {
1020
+        try {
1021
+            $userFolder = $this->rootFolder->getUserFolder($userId);
1022
+        } catch (NoUserException $e) {
1023
+            throw new InvalidShare();
1024
+        }
1025
+
1026
+        $nodes = $userFolder->getById($id);
1027
+
1028
+        if (empty($nodes)) {
1029
+            throw new InvalidShare();
1030
+        }
1031
+
1032
+        return $nodes[0];
1033
+    }
1034
+
1035
+    /**
1036
+     * A user is deleted from the system
1037
+     * So clean up the relevant shares.
1038
+     *
1039
+     * @param string $uid
1040
+     * @param int $shareType
1041
+     */
1042
+    public function userDeleted($uid, $shareType) {
1043
+        $qb = $this->dbConnection->getQueryBuilder();
1044
+
1045
+        $qb->delete('share')
1046
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
1047
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
1048
+            ->execute();
1049
+    }
1050
+
1051
+    /**
1052
+     * This provider does not support group shares
1053
+     *
1054
+     * @param string $gid
1055
+     */
1056
+    public function groupDeleted($gid) {
1057
+    }
1058
+
1059
+    /**
1060
+     * This provider does not support group shares
1061
+     *
1062
+     * @param string $uid
1063
+     * @param string $gid
1064
+     */
1065
+    public function userDeletedFromGroup($uid, $gid) {
1066
+    }
1067
+
1068
+    /**
1069
+     * get database row of a give share
1070
+     *
1071
+     * @param $id
1072
+     * @return array
1073
+     * @throws ShareNotFound
1074
+     */
1075
+    protected function getRawShare($id) {
1076
+
1077
+        // Now fetch the inserted share and create a complete share object
1078
+        $qb = $this->dbConnection->getQueryBuilder();
1079
+        $qb->select('*')
1080
+            ->from('share')
1081
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1082
+
1083
+        $cursor = $qb->execute();
1084
+        $data = $cursor->fetch();
1085
+        $cursor->closeCursor();
1086
+
1087
+        if ($data === false) {
1088
+            throw new ShareNotFound;
1089
+        }
1090
+
1091
+        return $data;
1092
+    }
1093
+
1094
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
1095
+        $qb = $this->dbConnection->getQueryBuilder();
1096
+        $qb->select('*')
1097
+            ->from('share', 's')
1098
+            ->andWhere($qb->expr()->orX(
1099
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1100
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1101
+            ))
1102
+            ->andWhere(
1103
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
1104
+            );
1105
+
1106
+        /**
1107
+         * Reshares for this user are shares where they are the owner.
1108
+         */
1109
+        if ($reshares === false) {
1110
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1111
+        } else {
1112
+            $qb->andWhere(
1113
+                $qb->expr()->orX(
1114
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1115
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1116
+                )
1117
+            );
1118
+        }
1119
+
1120
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1121
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1122
+
1123
+        $qb->orderBy('id');
1124
+
1125
+        $cursor = $qb->execute();
1126
+        $shares = [];
1127
+        while ($data = $cursor->fetch()) {
1128
+            $shares[$data['fileid']][] = $this->createShareObject($data);
1129
+        }
1130
+        $cursor->closeCursor();
1131
+
1132
+        return $shares;
1133
+    }
1134
+
1135
+    /**
1136
+     * @inheritdoc
1137
+     */
1138
+    public function getAccessList($nodes, $currentAccess) {
1139
+        $ids = [];
1140
+        foreach ($nodes as $node) {
1141
+            $ids[] = $node->getId();
1142
+        }
1143
+
1144
+        $qb = $this->dbConnection->getQueryBuilder();
1145
+        $qb->select('share_with')
1146
+            ->from('share')
1147
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
1148
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1149
+            ->andWhere($qb->expr()->orX(
1150
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1151
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1152
+            ))
1153
+            ->setMaxResults(1);
1154
+        $cursor = $qb->execute();
1155
+
1156
+        $mail = $cursor->fetch() !== false;
1157
+        $cursor->closeCursor();
1158
+
1159
+        return ['public' => $mail];
1160
+    }
1161
+
1162
+    public function getAllShares(): iterable {
1163
+        $qb = $this->dbConnection->getQueryBuilder();
1164
+
1165
+        $qb->select('*')
1166
+            ->from('share')
1167
+            ->where(
1168
+                $qb->expr()->orX(
1169
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_EMAIL))
1170
+                )
1171
+            );
1172
+
1173
+        $cursor = $qb->execute();
1174
+        while ($data = $cursor->fetch()) {
1175
+            try {
1176
+                $share = $this->createShareObject($data);
1177
+            } catch (InvalidShare $e) {
1178
+                continue;
1179
+            } catch (ShareNotFound $e) {
1180
+                continue;
1181
+            }
1182
+
1183
+            yield $share;
1184
+        }
1185
+        $cursor->closeCursor();
1186
+    }
1187 1187
 }
Please login to merge, or discard this patch.
apps/sharebymail/lib/Settings/Admin.php 1 patch
Indentation   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -28,41 +28,41 @@
 block discarded – undo
28 28
 
29 29
 class Admin implements ISettings {
30 30
 
31
-	/** @var SettingsManager */
32
-	private $settingsManager;
31
+    /** @var SettingsManager */
32
+    private $settingsManager;
33 33
 
34
-	public function __construct(SettingsManager $settingsManager) {
35
-		$this->settingsManager = $settingsManager;
36
-	}
34
+    public function __construct(SettingsManager $settingsManager) {
35
+        $this->settingsManager = $settingsManager;
36
+    }
37 37
 
38
-	/**
39
-	 * @return TemplateResponse
40
-	 */
41
-	public function getForm() {
42
-		$parameters = [
43
-			'sendPasswordMail' => $this->settingsManager->sendPasswordByMail(),
44
-			'enforcePasswordProtection' => $this->settingsManager->enforcePasswordProtection(),
45
-			'replyToInitiator' => $this->settingsManager->replyToInitiator()
46
-		];
38
+    /**
39
+     * @return TemplateResponse
40
+     */
41
+    public function getForm() {
42
+        $parameters = [
43
+            'sendPasswordMail' => $this->settingsManager->sendPasswordByMail(),
44
+            'enforcePasswordProtection' => $this->settingsManager->enforcePasswordProtection(),
45
+            'replyToInitiator' => $this->settingsManager->replyToInitiator()
46
+        ];
47 47
 
48
-		return new TemplateResponse('sharebymail', 'settings-admin', $parameters, '');
49
-	}
48
+        return new TemplateResponse('sharebymail', 'settings-admin', $parameters, '');
49
+    }
50 50
 
51
-	/**
52
-	 * @return string the section ID, e.g. 'sharing'
53
-	 */
54
-	public function getSection() {
55
-		return 'sharing';
56
-	}
51
+    /**
52
+     * @return string the section ID, e.g. 'sharing'
53
+     */
54
+    public function getSection() {
55
+        return 'sharing';
56
+    }
57 57
 
58
-	/**
59
-	 * @return int whether the form should be rather on the top or bottom of
60
-	 * the admin section. The forms are arranged in ascending order of the
61
-	 * priority values. It is required to return a value between 0 and 100.
62
-	 *
63
-	 * E.g.: 70
64
-	 */
65
-	public function getPriority() {
66
-		return 40;
67
-	}
58
+    /**
59
+     * @return int whether the form should be rather on the top or bottom of
60
+     * the admin section. The forms are arranged in ascending order of the
61
+     * priority values. It is required to return a value between 0 and 100.
62
+     *
63
+     * E.g.: 70
64
+     */
65
+    public function getPriority() {
66
+        return 40;
67
+    }
68 68
 }
Please login to merge, or discard this patch.
apps/sharebymail/lib/Settings/SettingsManager.php 1 patch
Indentation   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -31,46 +31,46 @@
 block discarded – undo
31 31
 
32 32
 class SettingsManager {
33 33
 
34
-	/** @var IConfig */
35
-	private $config;
34
+    /** @var IConfig */
35
+    private $config;
36 36
 
37
-	private $sendPasswordByMailDefault = 'yes';
37
+    private $sendPasswordByMailDefault = 'yes';
38 38
 
39
-	private $enforcePasswordProtectionDefault = 'no';
39
+    private $enforcePasswordProtectionDefault = 'no';
40 40
 
41
-	private $replyToInitiatorDefault = 'yes';
41
+    private $replyToInitiatorDefault = 'yes';
42 42
 
43
-	public function __construct(IConfig $config) {
44
-		$this->config = $config;
45
-	}
43
+    public function __construct(IConfig $config) {
44
+        $this->config = $config;
45
+    }
46 46
 
47
-	/**
48
-	 * should the password for a mail share be send to the recipient
49
-	 *
50
-	 * @return bool
51
-	 */
52
-	public function sendPasswordByMail(): bool {
53
-		$sendPasswordByMail = $this->config->getAppValue('sharebymail', 'sendpasswordmail', $this->sendPasswordByMailDefault);
54
-		return $sendPasswordByMail === 'yes';
55
-	}
47
+    /**
48
+     * should the password for a mail share be send to the recipient
49
+     *
50
+     * @return bool
51
+     */
52
+    public function sendPasswordByMail(): bool {
53
+        $sendPasswordByMail = $this->config->getAppValue('sharebymail', 'sendpasswordmail', $this->sendPasswordByMailDefault);
54
+        return $sendPasswordByMail === 'yes';
55
+    }
56 56
 
57
-	/**
58
-	 * do we require a share by mail to be password protected
59
-	 *
60
-	 * @return bool
61
-	 */
62
-	public function enforcePasswordProtection(): bool {
63
-		$enforcePassword = $this->config->getAppValue('sharebymail', 'enforcePasswordProtection', $this->enforcePasswordProtectionDefault);
64
-		return $enforcePassword === 'yes';
65
-	}
57
+    /**
58
+     * do we require a share by mail to be password protected
59
+     *
60
+     * @return bool
61
+     */
62
+    public function enforcePasswordProtection(): bool {
63
+        $enforcePassword = $this->config->getAppValue('sharebymail', 'enforcePasswordProtection', $this->enforcePasswordProtectionDefault);
64
+        return $enforcePassword === 'yes';
65
+    }
66 66
 
67
-	/**
68
-	 * should add reply to with initiator mail
69
-	 *
70
-	 * @return bool
71
-	 */
72
-	public function replyToInitiator(): bool {
73
-		$replyToInitiator =  $this->config->getAppValue('sharebymail', 'replyToInitiator', $this->replyToInitiatorDefault);
74
-		return $replyToInitiator === 'yes';
75
-	}
67
+    /**
68
+     * should add reply to with initiator mail
69
+     *
70
+     * @return bool
71
+     */
72
+    public function replyToInitiator(): bool {
73
+        $replyToInitiator =  $this->config->getAppValue('sharebymail', 'replyToInitiator', $this->replyToInitiatorDefault);
74
+        return $replyToInitiator === 'yes';
75
+    }
76 76
 }
Please login to merge, or discard this patch.
apps/sharebymail/templates/settings-admin.php 1 patch
Indentation   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -11,15 +11,15 @@
 block discarded – undo
11 11
 
12 12
 	<p>
13 13
 		<input id="sendPasswordMail" type="checkbox" class="checkbox" <?php if ($_['sendPasswordMail']) {
14
-	p('checked');
14
+    p('checked');
15 15
 } ?> />
16 16
 		<label for="sendPasswordMail"><?php p($l->t('Send password by mail')); ?></label><br/>
17 17
 		<input id="enforcePasswordProtection" type="checkbox" class="checkbox" <?php if ($_['enforcePasswordProtection']) {
18
-	p('checked');
18
+    p('checked');
19 19
 } ?> />
20 20
 		<label for="enforcePasswordProtection"><?php p($l->t('Enforce password protection')); ?></label><br/>
21 21
         <input id="replyToInitiator" type="checkbox" class="checkbox" <?php if ($_['replyToInitiator']) {
22
-	p('checked');
22
+    p('checked');
23 23
 } ?> />
24 24
         <label for="replyToInitiator"><?php p($l->t('Reply to initiator')); ?></label>
25 25
 	</p>
Please login to merge, or discard this patch.