Completed
Pull Request — master (#6288)
by Morris
17:43
created
apps/sharebymail/lib/ShareByMailProvider.php 2 patches
Indentation   +1007 added lines, -1007 removed lines patch added patch discarded remove patch
@@ -53,1025 +53,1025 @@
 block discarded – undo
53 53
  */
54 54
 class ShareByMailProvider implements IShareProvider {
55 55
 
56
-	/** @var  IDBConnection */
57
-	private $dbConnection;
58
-
59
-	/** @var ILogger */
60
-	private $logger;
61
-
62
-	/** @var ISecureRandom */
63
-	private $secureRandom;
64
-
65
-	/** @var IUserManager */
66
-	private $userManager;
67
-
68
-	/** @var IRootFolder */
69
-	private $rootFolder;
70
-
71
-	/** @var IL10N */
72
-	private $l;
73
-
74
-	/** @var IMailer */
75
-	private $mailer;
76
-
77
-	/** @var IURLGenerator */
78
-	private $urlGenerator;
79
-
80
-	/** @var IManager  */
81
-	private $activityManager;
82
-
83
-	/** @var SettingsManager */
84
-	private $settingsManager;
85
-
86
-	/** @var Defaults */
87
-	private $defaults;
88
-
89
-	/** @var IHasher */
90
-	private $hasher;
91
-
92
-	/** @var  CapabilitiesManager */
93
-	private $capabilitiesManager;
94
-
95
-	/**
96
-	 * Return the identifier of this provider.
97
-	 *
98
-	 * @return string Containing only [a-zA-Z0-9]
99
-	 */
100
-	public function identifier() {
101
-		return 'ocMailShare';
102
-	}
103
-
104
-	/**
105
-	 * DefaultShareProvider constructor.
106
-	 *
107
-	 * @param IDBConnection $connection
108
-	 * @param ISecureRandom $secureRandom
109
-	 * @param IUserManager $userManager
110
-	 * @param IRootFolder $rootFolder
111
-	 * @param IL10N $l
112
-	 * @param ILogger $logger
113
-	 * @param IMailer $mailer
114
-	 * @param IURLGenerator $urlGenerator
115
-	 * @param IManager $activityManager
116
-	 * @param SettingsManager $settingsManager
117
-	 * @param Defaults $defaults
118
-	 * @param IHasher $hasher
119
-	 * @param CapabilitiesManager $capabilitiesManager
120
-	 */
121
-	public function __construct(
122
-		IDBConnection $connection,
123
-		ISecureRandom $secureRandom,
124
-		IUserManager $userManager,
125
-		IRootFolder $rootFolder,
126
-		IL10N $l,
127
-		ILogger $logger,
128
-		IMailer $mailer,
129
-		IURLGenerator $urlGenerator,
130
-		IManager $activityManager,
131
-		SettingsManager $settingsManager,
132
-		Defaults $defaults,
133
-		IHasher $hasher,
134
-		CapabilitiesManager $capabilitiesManager
135
-	) {
136
-		$this->dbConnection = $connection;
137
-		$this->secureRandom = $secureRandom;
138
-		$this->userManager = $userManager;
139
-		$this->rootFolder = $rootFolder;
140
-		$this->l = $l;
141
-		$this->logger = $logger;
142
-		$this->mailer = $mailer;
143
-		$this->urlGenerator = $urlGenerator;
144
-		$this->activityManager = $activityManager;
145
-		$this->settingsManager = $settingsManager;
146
-		$this->defaults = $defaults;
147
-		$this->hasher = $hasher;
148
-		$this->capabilitiesManager = $capabilitiesManager;
149
-	}
150
-
151
-	/**
152
-	 * Share a path
153
-	 *
154
-	 * @param IShare $share
155
-	 * @return IShare The share object
156
-	 * @throws ShareNotFound
157
-	 * @throws \Exception
158
-	 */
159
-	public function create(IShare $share) {
160
-
161
-		$shareWith = $share->getSharedWith();
162
-		/*
56
+    /** @var  IDBConnection */
57
+    private $dbConnection;
58
+
59
+    /** @var ILogger */
60
+    private $logger;
61
+
62
+    /** @var ISecureRandom */
63
+    private $secureRandom;
64
+
65
+    /** @var IUserManager */
66
+    private $userManager;
67
+
68
+    /** @var IRootFolder */
69
+    private $rootFolder;
70
+
71
+    /** @var IL10N */
72
+    private $l;
73
+
74
+    /** @var IMailer */
75
+    private $mailer;
76
+
77
+    /** @var IURLGenerator */
78
+    private $urlGenerator;
79
+
80
+    /** @var IManager  */
81
+    private $activityManager;
82
+
83
+    /** @var SettingsManager */
84
+    private $settingsManager;
85
+
86
+    /** @var Defaults */
87
+    private $defaults;
88
+
89
+    /** @var IHasher */
90
+    private $hasher;
91
+
92
+    /** @var  CapabilitiesManager */
93
+    private $capabilitiesManager;
94
+
95
+    /**
96
+     * Return the identifier of this provider.
97
+     *
98
+     * @return string Containing only [a-zA-Z0-9]
99
+     */
100
+    public function identifier() {
101
+        return 'ocMailShare';
102
+    }
103
+
104
+    /**
105
+     * DefaultShareProvider constructor.
106
+     *
107
+     * @param IDBConnection $connection
108
+     * @param ISecureRandom $secureRandom
109
+     * @param IUserManager $userManager
110
+     * @param IRootFolder $rootFolder
111
+     * @param IL10N $l
112
+     * @param ILogger $logger
113
+     * @param IMailer $mailer
114
+     * @param IURLGenerator $urlGenerator
115
+     * @param IManager $activityManager
116
+     * @param SettingsManager $settingsManager
117
+     * @param Defaults $defaults
118
+     * @param IHasher $hasher
119
+     * @param CapabilitiesManager $capabilitiesManager
120
+     */
121
+    public function __construct(
122
+        IDBConnection $connection,
123
+        ISecureRandom $secureRandom,
124
+        IUserManager $userManager,
125
+        IRootFolder $rootFolder,
126
+        IL10N $l,
127
+        ILogger $logger,
128
+        IMailer $mailer,
129
+        IURLGenerator $urlGenerator,
130
+        IManager $activityManager,
131
+        SettingsManager $settingsManager,
132
+        Defaults $defaults,
133
+        IHasher $hasher,
134
+        CapabilitiesManager $capabilitiesManager
135
+    ) {
136
+        $this->dbConnection = $connection;
137
+        $this->secureRandom = $secureRandom;
138
+        $this->userManager = $userManager;
139
+        $this->rootFolder = $rootFolder;
140
+        $this->l = $l;
141
+        $this->logger = $logger;
142
+        $this->mailer = $mailer;
143
+        $this->urlGenerator = $urlGenerator;
144
+        $this->activityManager = $activityManager;
145
+        $this->settingsManager = $settingsManager;
146
+        $this->defaults = $defaults;
147
+        $this->hasher = $hasher;
148
+        $this->capabilitiesManager = $capabilitiesManager;
149
+    }
150
+
151
+    /**
152
+     * Share a path
153
+     *
154
+     * @param IShare $share
155
+     * @return IShare The share object
156
+     * @throws ShareNotFound
157
+     * @throws \Exception
158
+     */
159
+    public function create(IShare $share) {
160
+
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, \OCP\Share::SHARE_TYPE_EMAIL, $share->getNode(), 1, 0);
166
-		if (!empty($alreadyShared)) {
167
-			$message = 'Sharing %s failed, this item is already shared with %s';
168
-			$message_t = $this->l->t('Sharing %s failed, this item is already shared with %s', array($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 = '';
176
-		$passwordEnforced = $this->settingsManager->enforcePasswordProtection();
177
-		if ($passwordEnforced) {
178
-			$password = $this->autoGeneratePassword($share);
179
-		}
180
-
181
-		$shareId = $this->createMailShare($share);
182
-		$send = $this->sendPassword($share, $password);
183
-		if ($passwordEnforced && $send === false) {
184
-			$this->sendPasswordToOwner($share, $password);
185
-		}
186
-
187
-		$this->createShareActivity($share);
188
-		$data = $this->getRawShare($shareId);
189
-
190
-		return $this->createShareObject($data);
191
-
192
-	}
193
-
194
-	/**
195
-	 * auto generate password in case of password enforcement on mail shares
196
-	 *
197
-	 * @param IShare $share
198
-	 * @return string
199
-	 * @throws \Exception
200
-	 */
201
-	protected function autoGeneratePassword($share) {
202
-		$initiatorUser = $this->userManager->get($share->getSharedBy());
203
-		$initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
204
-		$allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
205
-
206
-		if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
207
-			throw new \Exception(
208
-				$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.")
209
-			);
210
-		}
211
-
212
-		$passwordPolicy = $this->getPasswordPolicy();
213
-		$passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS;
214
-		$passwordLength = 8;
215
-		if (!empty($passwordPolicy)) {
216
-			$passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength;
217
-			$passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : '';
218
-		}
219
-
220
-		$password = $this->secureRandom->generate($passwordLength, $passwordCharset);
221
-
222
-		$share->setPassword($this->hasher->hash($password));
223
-
224
-		return $password;
225
-	}
226
-
227
-	/**
228
-	 * get password policy
229
-	 *
230
-	 * @return array
231
-	 */
232
-	protected function getPasswordPolicy() {
233
-		$capabilities = $this->capabilitiesManager->getCapabilities();
234
-		if (isset($capabilities['password_policy'])) {
235
-			return $capabilities['password_policy'];
236
-		}
237
-
238
-		return [];
239
-	}
240
-
241
-	/**
242
-	 * create activity if a file/folder was shared by mail
243
-	 *
244
-	 * @param IShare $share
245
-	 */
246
-	protected function createShareActivity(IShare $share) {
247
-
248
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
249
-
250
-		$this->publishActivity(
251
-			Activity::SUBJECT_SHARED_EMAIL_SELF,
252
-			[$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
253
-			$share->getSharedBy(),
254
-			$share->getNode()->getId(),
255
-			$userFolder->getRelativePath($share->getNode()->getPath())
256
-		);
257
-
258
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
259
-			$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
260
-			$fileId = $share->getNode()->getId();
261
-			$nodes = $ownerFolder->getById($fileId);
262
-			$ownerPath = $nodes[0]->getPath();
263
-			$this->publishActivity(
264
-				Activity::SUBJECT_SHARED_EMAIL_BY,
265
-				[$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
266
-				$share->getShareOwner(),
267
-				$fileId,
268
-				$ownerFolder->getRelativePath($ownerPath)
269
-			);
270
-		}
271
-
272
-	}
273
-
274
-	/**
275
-	 * create activity if a file/folder was shared by mail
276
-	 *
277
-	 * @param IShare $share
278
-	 * @param string $sharedWith
279
-	 * @param bool $sendToSelf
280
-	 */
281
-	protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) {
282
-
283
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
284
-
285
-		if ($sendToSelf) {
286
-			$this->publishActivity(
287
-				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
288
-				[$userFolder->getRelativePath($share->getNode()->getPath())],
289
-				$share->getSharedBy(),
290
-				$share->getNode()->getId(),
291
-				$userFolder->getRelativePath($share->getNode()->getPath())
292
-			);
293
-		} else {
294
-			$this->publishActivity(
295
-				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
296
-				[$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
297
-				$share->getSharedBy(),
298
-				$share->getNode()->getId(),
299
-				$userFolder->getRelativePath($share->getNode()->getPath())
300
-			);
301
-		}
302
-	}
303
-
304
-
305
-	/**
306
-	 * publish activity if a file/folder was shared by mail
307
-	 *
308
-	 * @param $subject
309
-	 * @param $parameters
310
-	 * @param $affectedUser
311
-	 * @param $fileId
312
-	 * @param $filePath
313
-	 */
314
-	protected function publishActivity($subject, $parameters, $affectedUser, $fileId, $filePath) {
315
-		$event = $this->activityManager->generateEvent();
316
-		$event->setApp('sharebymail')
317
-			->setType('shared')
318
-			->setSubject($subject, $parameters)
319
-			->setAffectedUser($affectedUser)
320
-			->setObject('files', $fileId, $filePath);
321
-		$this->activityManager->publish($event);
322
-
323
-	}
324
-
325
-	/**
326
-	 * @param IShare $share
327
-	 * @return int
328
-	 * @throws \Exception
329
-	 */
330
-	protected function createMailShare(IShare $share) {
331
-		$share->setToken($this->generateToken());
332
-		$shareId = $this->addShareToDB(
333
-			$share->getNodeId(),
334
-			$share->getNodeType(),
335
-			$share->getSharedWith(),
336
-			$share->getSharedBy(),
337
-			$share->getShareOwner(),
338
-			$share->getPermissions(),
339
-			$share->getToken(),
340
-			$share->getPassword()
341
-		);
342
-
343
-		try {
344
-			$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
345
-				['token' => $share->getToken()]);
346
-			$this->sendMailNotification(
347
-				$share->getNode()->getName(),
348
-				$link,
349
-				$share->getSharedBy(),
350
-				$share->getSharedWith(),
351
-				$share->getExpirationDate()
352
-			);
353
-		} catch (HintException $hintException) {
354
-			$this->logger->error('Failed to send share by mail: ' . $hintException->getMessage());
355
-			$this->removeShareFromTable($shareId);
356
-			throw $hintException;
357
-		} catch (\Exception $e) {
358
-			$this->logger->error('Failed to send share by email: ' . $e->getMessage());
359
-			$this->removeShareFromTable($shareId);
360
-			throw new HintException('Failed to send share by mail',
361
-				$this->l->t('Failed to send share by email'));
362
-		}
363
-
364
-		return $shareId;
365
-
366
-	}
367
-
368
-	/**
369
-	 * @param string $filename
370
-	 * @param string $link
371
-	 * @param string $initiator
372
-	 * @param string $shareWith
373
-	 * @param \DateTime|null $expiration
374
-	 * @throws \Exception If mail couldn't be sent
375
-	 */
376
-	protected function sendMailNotification($filename,
377
-											$link,
378
-											$initiator,
379
-											$shareWith,
380
-											\DateTime $expiration = null) {
381
-		$initiatorUser = $this->userManager->get($initiator);
382
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
383
-		$subject = (string)$this->l->t('%s shared »%s« with you', array($initiatorDisplayName, $filename));
384
-
385
-		$message = $this->mailer->createMessage();
386
-
387
-		$emailTemplate = $this->mailer->createEMailTemplate();
388
-		$emailTemplate->setMetaData('sharebymail.RecipientNotification', [
389
-			'filename' => $filename,
390
-			'link' => $link,
391
-			'initiator' => $initiatorDisplayName,
392
-			'expiration' => $expiration,
393
-		]);
394
-
395
-		$emailTemplate->addHeader();
396
-		$emailTemplate->addHeading($this->l->t('%s shared »%s« with you', [$initiatorDisplayName, $filename]), false);
397
-		$text = $this->l->t('%s shared »%s« with you.', [$initiatorDisplayName, $filename]);
398
-
399
-		$emailTemplate->addBodyText(
400
-			$text . ' ' . $this->l->t('Click the button below to open it.'),
401
-			$text
402
-		);
403
-		$emailTemplate->addBodyButton(
404
-			$this->l->t('Open »%s«', [$filename]),
405
-			$link
406
-		);
407
-
408
-		$message->setTo([$shareWith]);
409
-
410
-		// The "From" contains the sharers name
411
-		$instanceName = $this->defaults->getName();
412
-		$senderName = $this->l->t(
413
-			'%s via %s',
414
-			[
415
-				$initiatorDisplayName,
416
-				$instanceName
417
-			]
418
-		);
419
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
420
-
421
-		// The "Reply-To" is set to the sharer if an mail address is configured
422
-		// also the default footer contains a "Do not reply" which needs to be adjusted.
423
-		$initiatorEmail = $initiatorUser->getEMailAddress();
424
-		if($initiatorEmail !== null) {
425
-			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
426
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
427
-		} else {
428
-			$emailTemplate->addFooter();
429
-		}
430
-
431
-		$message->setSubject($subject);
432
-		$message->setPlainBody($emailTemplate->renderText());
433
-		$message->setHtmlBody($emailTemplate->renderHtml());
434
-		$this->mailer->send($message);
435
-	}
436
-
437
-	/**
438
-	 * send password to recipient of a mail share
439
-	 *
440
-	 * @param IShare $share
441
-	 * @param string $password
442
-	 * @return bool
443
-	 */
444
-	protected function sendPassword(IShare $share, $password) {
445
-
446
-		$filename = $share->getNode()->getName();
447
-		$initiator = $share->getSharedBy();
448
-		$shareWith = $share->getSharedWith();
449
-
450
-		if ($password === '' || $this->settingsManager->sendPasswordByMail() === false) {
451
-			return false;
452
-		}
453
-
454
-		$initiatorUser = $this->userManager->get($initiator);
455
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
456
-		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
457
-
458
-		$subject = (string)$this->l->t('Password to access »%s« shared to you by %s', [$filename, $initiatorDisplayName]);
459
-		$plainBodyPart = $this->l->t("%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]);
460
-		$htmlBodyPart = $this->l->t('%s shared »%s« with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
461
-
462
-		$message = $this->mailer->createMessage();
463
-
464
-		$emailTemplate = $this->mailer->createEMailTemplate();
465
-		$emailTemplate->addHeader();
466
-		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
467
-		$emailTemplate->addBodyText($htmlBodyPart, $plainBodyPart);
468
-		$emailTemplate->addBodyText($this->l->t('It is protected with the following password: %s', [$password]));
469
-
470
-		// The "From" contains the sharers name
471
-		$instanceName = $this->defaults->getName();
472
-		$senderName = $this->l->t(
473
-			'%s via %s',
474
-			[
475
-				$initiatorDisplayName,
476
-				$instanceName
477
-			]
478
-		);
479
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
480
-		if ($initiatorEmailAddress !== null) {
481
-			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
482
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
483
-		} else {
484
-			$emailTemplate->addFooter();
485
-		}
486
-
487
-		$message->setTo([$shareWith]);
488
-		$message->setSubject($subject);
489
-		$message->setBody($emailTemplate->renderText(), 'text/plain');
490
-		$message->setHtmlBody($emailTemplate->renderHtml());
491
-		$this->mailer->send($message);
492
-
493
-		$this->createPasswordSendActivity($share, $shareWith, false);
494
-
495
-		return true;
496
-	}
497
-
498
-	/**
499
-	 * send auto generated password to the owner. This happens if the admin enforces
500
-	 * a password for mail shares and forbid to send the password by mail to the recipient
501
-	 *
502
-	 * @param IShare $share
503
-	 * @param string $password
504
-	 * @return bool
505
-	 * @throws \Exception
506
-	 */
507
-	protected function sendPasswordToOwner(IShare $share, $password) {
508
-
509
-		$filename = $share->getNode()->getName();
510
-		$initiator = $this->userManager->get($share->getSharedBy());
511
-		$initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
512
-		$initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
513
-		$shareWith = $share->getSharedWith();
514
-
515
-		if ($initiatorEMailAddress === null) {
516
-			throw new \Exception(
517
-				$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.")
518
-			);
519
-		}
520
-
521
-		$subject = (string)$this->l->t('Password to access »%s« shared with %s', [$filename, $shareWith]);
522
-		$bodyPart = $this->l->t("You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %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()]);
523
-
524
-		$message = $this->mailer->createMessage();
525
-		$emailTemplate = $this->mailer->createEMailTemplate();
526
-
527
-		$emailTemplate->addHeader();
528
-		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
529
-		$emailTemplate->addBodyText($bodyPart);
530
-		$emailTemplate->addBodyText($this->l->t('This is the password: %s', [$password]));
531
-		$emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
532
-		$emailTemplate->addFooter();
533
-
534
-		if ($initiatorEMailAddress) {
535
-			$message->setFrom([$initiatorEMailAddress => $initiatorDisplayName]);
536
-		}
537
-		$message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
538
-		$message->setSubject($subject);
539
-		$message->setBody($emailTemplate->renderText(), 'text/plain');
540
-		$message->setHtmlBody($emailTemplate->renderHtml());
541
-		$this->mailer->send($message);
542
-
543
-		$this->createPasswordSendActivity($share, $shareWith, true);
544
-
545
-		return true;
546
-	}
547
-
548
-	/**
549
-	 * generate share token
550
-	 *
551
-	 * @return string
552
-	 */
553
-	protected function generateToken($size = 15) {
554
-		$token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
555
-		return $token;
556
-	}
557
-
558
-	/**
559
-	 * Get all children of this share
560
-	 *
561
-	 * @param IShare $parent
562
-	 * @return IShare[]
563
-	 */
564
-	public function getChildren(IShare $parent) {
565
-		$children = [];
566
-
567
-		$qb = $this->dbConnection->getQueryBuilder();
568
-		$qb->select('*')
569
-			->from('share')
570
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
571
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
572
-			->orderBy('id');
573
-
574
-		$cursor = $qb->execute();
575
-		while($data = $cursor->fetch()) {
576
-			$children[] = $this->createShareObject($data);
577
-		}
578
-		$cursor->closeCursor();
579
-
580
-		return $children;
581
-	}
582
-
583
-	/**
584
-	 * add share to the database and return the ID
585
-	 *
586
-	 * @param int $itemSource
587
-	 * @param string $itemType
588
-	 * @param string $shareWith
589
-	 * @param string $sharedBy
590
-	 * @param string $uidOwner
591
-	 * @param int $permissions
592
-	 * @param string $token
593
-	 * @return int
594
-	 */
595
-	protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password) {
596
-		$qb = $this->dbConnection->getQueryBuilder();
597
-		$qb->insert('share')
598
-			->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
599
-			->setValue('item_type', $qb->createNamedParameter($itemType))
600
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
601
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
602
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
603
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
604
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
605
-			->setValue('permissions', $qb->createNamedParameter($permissions))
606
-			->setValue('token', $qb->createNamedParameter($token))
607
-			->setValue('password', $qb->createNamedParameter($password))
608
-			->setValue('stime', $qb->createNamedParameter(time()));
609
-
610
-		/*
165
+        $alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_EMAIL, $share->getNode(), 1, 0);
166
+        if (!empty($alreadyShared)) {
167
+            $message = 'Sharing %s failed, this item is already shared with %s';
168
+            $message_t = $this->l->t('Sharing %s failed, this item is already shared with %s', array($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 = '';
176
+        $passwordEnforced = $this->settingsManager->enforcePasswordProtection();
177
+        if ($passwordEnforced) {
178
+            $password = $this->autoGeneratePassword($share);
179
+        }
180
+
181
+        $shareId = $this->createMailShare($share);
182
+        $send = $this->sendPassword($share, $password);
183
+        if ($passwordEnforced && $send === false) {
184
+            $this->sendPasswordToOwner($share, $password);
185
+        }
186
+
187
+        $this->createShareActivity($share);
188
+        $data = $this->getRawShare($shareId);
189
+
190
+        return $this->createShareObject($data);
191
+
192
+    }
193
+
194
+    /**
195
+     * auto generate password in case of password enforcement on mail shares
196
+     *
197
+     * @param IShare $share
198
+     * @return string
199
+     * @throws \Exception
200
+     */
201
+    protected function autoGeneratePassword($share) {
202
+        $initiatorUser = $this->userManager->get($share->getSharedBy());
203
+        $initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
204
+        $allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
205
+
206
+        if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
207
+            throw new \Exception(
208
+                $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.")
209
+            );
210
+        }
211
+
212
+        $passwordPolicy = $this->getPasswordPolicy();
213
+        $passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS;
214
+        $passwordLength = 8;
215
+        if (!empty($passwordPolicy)) {
216
+            $passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength;
217
+            $passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : '';
218
+        }
219
+
220
+        $password = $this->secureRandom->generate($passwordLength, $passwordCharset);
221
+
222
+        $share->setPassword($this->hasher->hash($password));
223
+
224
+        return $password;
225
+    }
226
+
227
+    /**
228
+     * get password policy
229
+     *
230
+     * @return array
231
+     */
232
+    protected function getPasswordPolicy() {
233
+        $capabilities = $this->capabilitiesManager->getCapabilities();
234
+        if (isset($capabilities['password_policy'])) {
235
+            return $capabilities['password_policy'];
236
+        }
237
+
238
+        return [];
239
+    }
240
+
241
+    /**
242
+     * create activity if a file/folder was shared by mail
243
+     *
244
+     * @param IShare $share
245
+     */
246
+    protected function createShareActivity(IShare $share) {
247
+
248
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
249
+
250
+        $this->publishActivity(
251
+            Activity::SUBJECT_SHARED_EMAIL_SELF,
252
+            [$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
253
+            $share->getSharedBy(),
254
+            $share->getNode()->getId(),
255
+            $userFolder->getRelativePath($share->getNode()->getPath())
256
+        );
257
+
258
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
259
+            $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
260
+            $fileId = $share->getNode()->getId();
261
+            $nodes = $ownerFolder->getById($fileId);
262
+            $ownerPath = $nodes[0]->getPath();
263
+            $this->publishActivity(
264
+                Activity::SUBJECT_SHARED_EMAIL_BY,
265
+                [$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
266
+                $share->getShareOwner(),
267
+                $fileId,
268
+                $ownerFolder->getRelativePath($ownerPath)
269
+            );
270
+        }
271
+
272
+    }
273
+
274
+    /**
275
+     * create activity if a file/folder was shared by mail
276
+     *
277
+     * @param IShare $share
278
+     * @param string $sharedWith
279
+     * @param bool $sendToSelf
280
+     */
281
+    protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) {
282
+
283
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
284
+
285
+        if ($sendToSelf) {
286
+            $this->publishActivity(
287
+                Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
288
+                [$userFolder->getRelativePath($share->getNode()->getPath())],
289
+                $share->getSharedBy(),
290
+                $share->getNode()->getId(),
291
+                $userFolder->getRelativePath($share->getNode()->getPath())
292
+            );
293
+        } else {
294
+            $this->publishActivity(
295
+                Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
296
+                [$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
297
+                $share->getSharedBy(),
298
+                $share->getNode()->getId(),
299
+                $userFolder->getRelativePath($share->getNode()->getPath())
300
+            );
301
+        }
302
+    }
303
+
304
+
305
+    /**
306
+     * publish activity if a file/folder was shared by mail
307
+     *
308
+     * @param $subject
309
+     * @param $parameters
310
+     * @param $affectedUser
311
+     * @param $fileId
312
+     * @param $filePath
313
+     */
314
+    protected function publishActivity($subject, $parameters, $affectedUser, $fileId, $filePath) {
315
+        $event = $this->activityManager->generateEvent();
316
+        $event->setApp('sharebymail')
317
+            ->setType('shared')
318
+            ->setSubject($subject, $parameters)
319
+            ->setAffectedUser($affectedUser)
320
+            ->setObject('files', $fileId, $filePath);
321
+        $this->activityManager->publish($event);
322
+
323
+    }
324
+
325
+    /**
326
+     * @param IShare $share
327
+     * @return int
328
+     * @throws \Exception
329
+     */
330
+    protected function createMailShare(IShare $share) {
331
+        $share->setToken($this->generateToken());
332
+        $shareId = $this->addShareToDB(
333
+            $share->getNodeId(),
334
+            $share->getNodeType(),
335
+            $share->getSharedWith(),
336
+            $share->getSharedBy(),
337
+            $share->getShareOwner(),
338
+            $share->getPermissions(),
339
+            $share->getToken(),
340
+            $share->getPassword()
341
+        );
342
+
343
+        try {
344
+            $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
345
+                ['token' => $share->getToken()]);
346
+            $this->sendMailNotification(
347
+                $share->getNode()->getName(),
348
+                $link,
349
+                $share->getSharedBy(),
350
+                $share->getSharedWith(),
351
+                $share->getExpirationDate()
352
+            );
353
+        } catch (HintException $hintException) {
354
+            $this->logger->error('Failed to send share by mail: ' . $hintException->getMessage());
355
+            $this->removeShareFromTable($shareId);
356
+            throw $hintException;
357
+        } catch (\Exception $e) {
358
+            $this->logger->error('Failed to send share by email: ' . $e->getMessage());
359
+            $this->removeShareFromTable($shareId);
360
+            throw new HintException('Failed to send share by mail',
361
+                $this->l->t('Failed to send share by email'));
362
+        }
363
+
364
+        return $shareId;
365
+
366
+    }
367
+
368
+    /**
369
+     * @param string $filename
370
+     * @param string $link
371
+     * @param string $initiator
372
+     * @param string $shareWith
373
+     * @param \DateTime|null $expiration
374
+     * @throws \Exception If mail couldn't be sent
375
+     */
376
+    protected function sendMailNotification($filename,
377
+                                            $link,
378
+                                            $initiator,
379
+                                            $shareWith,
380
+                                            \DateTime $expiration = null) {
381
+        $initiatorUser = $this->userManager->get($initiator);
382
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
383
+        $subject = (string)$this->l->t('%s shared »%s« with you', array($initiatorDisplayName, $filename));
384
+
385
+        $message = $this->mailer->createMessage();
386
+
387
+        $emailTemplate = $this->mailer->createEMailTemplate();
388
+        $emailTemplate->setMetaData('sharebymail.RecipientNotification', [
389
+            'filename' => $filename,
390
+            'link' => $link,
391
+            'initiator' => $initiatorDisplayName,
392
+            'expiration' => $expiration,
393
+        ]);
394
+
395
+        $emailTemplate->addHeader();
396
+        $emailTemplate->addHeading($this->l->t('%s shared »%s« with you', [$initiatorDisplayName, $filename]), false);
397
+        $text = $this->l->t('%s shared »%s« with you.', [$initiatorDisplayName, $filename]);
398
+
399
+        $emailTemplate->addBodyText(
400
+            $text . ' ' . $this->l->t('Click the button below to open it.'),
401
+            $text
402
+        );
403
+        $emailTemplate->addBodyButton(
404
+            $this->l->t('Open »%s«', [$filename]),
405
+            $link
406
+        );
407
+
408
+        $message->setTo([$shareWith]);
409
+
410
+        // The "From" contains the sharers name
411
+        $instanceName = $this->defaults->getName();
412
+        $senderName = $this->l->t(
413
+            '%s via %s',
414
+            [
415
+                $initiatorDisplayName,
416
+                $instanceName
417
+            ]
418
+        );
419
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
420
+
421
+        // The "Reply-To" is set to the sharer if an mail address is configured
422
+        // also the default footer contains a "Do not reply" which needs to be adjusted.
423
+        $initiatorEmail = $initiatorUser->getEMailAddress();
424
+        if($initiatorEmail !== null) {
425
+            $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
426
+            $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
427
+        } else {
428
+            $emailTemplate->addFooter();
429
+        }
430
+
431
+        $message->setSubject($subject);
432
+        $message->setPlainBody($emailTemplate->renderText());
433
+        $message->setHtmlBody($emailTemplate->renderHtml());
434
+        $this->mailer->send($message);
435
+    }
436
+
437
+    /**
438
+     * send password to recipient of a mail share
439
+     *
440
+     * @param IShare $share
441
+     * @param string $password
442
+     * @return bool
443
+     */
444
+    protected function sendPassword(IShare $share, $password) {
445
+
446
+        $filename = $share->getNode()->getName();
447
+        $initiator = $share->getSharedBy();
448
+        $shareWith = $share->getSharedWith();
449
+
450
+        if ($password === '' || $this->settingsManager->sendPasswordByMail() === false) {
451
+            return false;
452
+        }
453
+
454
+        $initiatorUser = $this->userManager->get($initiator);
455
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
456
+        $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
457
+
458
+        $subject = (string)$this->l->t('Password to access »%s« shared to you by %s', [$filename, $initiatorDisplayName]);
459
+        $plainBodyPart = $this->l->t("%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]);
460
+        $htmlBodyPart = $this->l->t('%s shared »%s« with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
461
+
462
+        $message = $this->mailer->createMessage();
463
+
464
+        $emailTemplate = $this->mailer->createEMailTemplate();
465
+        $emailTemplate->addHeader();
466
+        $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
467
+        $emailTemplate->addBodyText($htmlBodyPart, $plainBodyPart);
468
+        $emailTemplate->addBodyText($this->l->t('It is protected with the following password: %s', [$password]));
469
+
470
+        // The "From" contains the sharers name
471
+        $instanceName = $this->defaults->getName();
472
+        $senderName = $this->l->t(
473
+            '%s via %s',
474
+            [
475
+                $initiatorDisplayName,
476
+                $instanceName
477
+            ]
478
+        );
479
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
480
+        if ($initiatorEmailAddress !== null) {
481
+            $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
482
+            $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
483
+        } else {
484
+            $emailTemplate->addFooter();
485
+        }
486
+
487
+        $message->setTo([$shareWith]);
488
+        $message->setSubject($subject);
489
+        $message->setBody($emailTemplate->renderText(), 'text/plain');
490
+        $message->setHtmlBody($emailTemplate->renderHtml());
491
+        $this->mailer->send($message);
492
+
493
+        $this->createPasswordSendActivity($share, $shareWith, false);
494
+
495
+        return true;
496
+    }
497
+
498
+    /**
499
+     * send auto generated password to the owner. This happens if the admin enforces
500
+     * a password for mail shares and forbid to send the password by mail to the recipient
501
+     *
502
+     * @param IShare $share
503
+     * @param string $password
504
+     * @return bool
505
+     * @throws \Exception
506
+     */
507
+    protected function sendPasswordToOwner(IShare $share, $password) {
508
+
509
+        $filename = $share->getNode()->getName();
510
+        $initiator = $this->userManager->get($share->getSharedBy());
511
+        $initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
512
+        $initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
513
+        $shareWith = $share->getSharedWith();
514
+
515
+        if ($initiatorEMailAddress === null) {
516
+            throw new \Exception(
517
+                $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.")
518
+            );
519
+        }
520
+
521
+        $subject = (string)$this->l->t('Password to access »%s« shared with %s', [$filename, $shareWith]);
522
+        $bodyPart = $this->l->t("You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %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()]);
523
+
524
+        $message = $this->mailer->createMessage();
525
+        $emailTemplate = $this->mailer->createEMailTemplate();
526
+
527
+        $emailTemplate->addHeader();
528
+        $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
529
+        $emailTemplate->addBodyText($bodyPart);
530
+        $emailTemplate->addBodyText($this->l->t('This is the password: %s', [$password]));
531
+        $emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
532
+        $emailTemplate->addFooter();
533
+
534
+        if ($initiatorEMailAddress) {
535
+            $message->setFrom([$initiatorEMailAddress => $initiatorDisplayName]);
536
+        }
537
+        $message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
538
+        $message->setSubject($subject);
539
+        $message->setBody($emailTemplate->renderText(), 'text/plain');
540
+        $message->setHtmlBody($emailTemplate->renderHtml());
541
+        $this->mailer->send($message);
542
+
543
+        $this->createPasswordSendActivity($share, $shareWith, true);
544
+
545
+        return true;
546
+    }
547
+
548
+    /**
549
+     * generate share token
550
+     *
551
+     * @return string
552
+     */
553
+    protected function generateToken($size = 15) {
554
+        $token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
555
+        return $token;
556
+    }
557
+
558
+    /**
559
+     * Get all children of this share
560
+     *
561
+     * @param IShare $parent
562
+     * @return IShare[]
563
+     */
564
+    public function getChildren(IShare $parent) {
565
+        $children = [];
566
+
567
+        $qb = $this->dbConnection->getQueryBuilder();
568
+        $qb->select('*')
569
+            ->from('share')
570
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
571
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
572
+            ->orderBy('id');
573
+
574
+        $cursor = $qb->execute();
575
+        while($data = $cursor->fetch()) {
576
+            $children[] = $this->createShareObject($data);
577
+        }
578
+        $cursor->closeCursor();
579
+
580
+        return $children;
581
+    }
582
+
583
+    /**
584
+     * add share to the database and return the ID
585
+     *
586
+     * @param int $itemSource
587
+     * @param string $itemType
588
+     * @param string $shareWith
589
+     * @param string $sharedBy
590
+     * @param string $uidOwner
591
+     * @param int $permissions
592
+     * @param string $token
593
+     * @return int
594
+     */
595
+    protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password) {
596
+        $qb = $this->dbConnection->getQueryBuilder();
597
+        $qb->insert('share')
598
+            ->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
599
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
600
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
601
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
602
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
603
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
604
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
605
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
606
+            ->setValue('token', $qb->createNamedParameter($token))
607
+            ->setValue('password', $qb->createNamedParameter($password))
608
+            ->setValue('stime', $qb->createNamedParameter(time()));
609
+
610
+        /*
611 611
 		 * Added to fix https://github.com/owncloud/core/issues/22215
612 612
 		 * Can be removed once we get rid of ajax/share.php
613 613
 		 */
614
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
614
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
615 615
 
616
-		$qb->execute();
617
-		$id = $qb->getLastInsertId();
616
+        $qb->execute();
617
+        $id = $qb->getLastInsertId();
618 618
 
619
-		return (int)$id;
620
-	}
619
+        return (int)$id;
620
+    }
621 621
 
622
-	/**
623
-	 * Update a share
624
-	 *
625
-	 * @param IShare $share
626
-	 * @param string|null $plainTextPassword
627
-	 * @return IShare The share object
628
-	 */
629
-	public function update(IShare $share, $plainTextPassword = null) {
622
+    /**
623
+     * Update a share
624
+     *
625
+     * @param IShare $share
626
+     * @param string|null $plainTextPassword
627
+     * @return IShare The share object
628
+     */
629
+    public function update(IShare $share, $plainTextPassword = null) {
630 630
 
631
-		$originalShare = $this->getShareById($share->getId());
631
+        $originalShare = $this->getShareById($share->getId());
632 632
 
633
-		// a real password was given
634
-		$validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
633
+        // a real password was given
634
+        $validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
635 635
 
636
-		if($validPassword && $originalShare->getPassword() !== $share->getPassword()) {
637
-			$this->sendPassword($share, $plainTextPassword);
638
-		}
639
-		/*
636
+        if($validPassword && $originalShare->getPassword() !== $share->getPassword()) {
637
+            $this->sendPassword($share, $plainTextPassword);
638
+        }
639
+        /*
640 640
 		 * We allow updating the permissions and password of mail shares
641 641
 		 */
642
-		$qb = $this->dbConnection->getQueryBuilder();
643
-		$qb->update('share')
644
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
645
-			->set('permissions', $qb->createNamedParameter($share->getPermissions()))
646
-			->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
647
-			->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
648
-			->set('password', $qb->createNamedParameter($share->getPassword()))
649
-			->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
650
-			->execute();
651
-
652
-		return $share;
653
-	}
654
-
655
-	/**
656
-	 * @inheritdoc
657
-	 */
658
-	public function move(IShare $share, $recipient) {
659
-		/**
660
-		 * nothing to do here, mail shares are only outgoing shares
661
-		 */
662
-		return $share;
663
-	}
664
-
665
-	/**
666
-	 * Delete a share (owner unShares the file)
667
-	 *
668
-	 * @param IShare $share
669
-	 */
670
-	public function delete(IShare $share) {
671
-		$this->removeShareFromTable($share->getId());
672
-	}
673
-
674
-	/**
675
-	 * @inheritdoc
676
-	 */
677
-	public function deleteFromSelf(IShare $share, $recipient) {
678
-		// nothing to do here, mail shares are only outgoing shares
679
-		return;
680
-	}
681
-
682
-	/**
683
-	 * @inheritdoc
684
-	 */
685
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
686
-		$qb = $this->dbConnection->getQueryBuilder();
687
-		$qb->select('*')
688
-			->from('share');
689
-
690
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
691
-
692
-		/**
693
-		 * Reshares for this user are shares where they are the owner.
694
-		 */
695
-		if ($reshares === false) {
696
-			//Special case for old shares created via the web UI
697
-			$or1 = $qb->expr()->andX(
698
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
699
-				$qb->expr()->isNull('uid_initiator')
700
-			);
701
-
702
-			$qb->andWhere(
703
-				$qb->expr()->orX(
704
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
705
-					$or1
706
-				)
707
-			);
708
-		} else {
709
-			$qb->andWhere(
710
-				$qb->expr()->orX(
711
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
712
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
713
-				)
714
-			);
715
-		}
716
-
717
-		if ($node !== null) {
718
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
719
-		}
720
-
721
-		if ($limit !== -1) {
722
-			$qb->setMaxResults($limit);
723
-		}
724
-
725
-		$qb->setFirstResult($offset);
726
-		$qb->orderBy('id');
727
-
728
-		$cursor = $qb->execute();
729
-		$shares = [];
730
-		while($data = $cursor->fetch()) {
731
-			$shares[] = $this->createShareObject($data);
732
-		}
733
-		$cursor->closeCursor();
734
-
735
-		return $shares;
736
-	}
737
-
738
-	/**
739
-	 * @inheritdoc
740
-	 */
741
-	public function getShareById($id, $recipientId = null) {
742
-		$qb = $this->dbConnection->getQueryBuilder();
743
-
744
-		$qb->select('*')
745
-			->from('share')
746
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
747
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
748
-
749
-		$cursor = $qb->execute();
750
-		$data = $cursor->fetch();
751
-		$cursor->closeCursor();
752
-
753
-		if ($data === false) {
754
-			throw new ShareNotFound();
755
-		}
756
-
757
-		try {
758
-			$share = $this->createShareObject($data);
759
-		} catch (InvalidShare $e) {
760
-			throw new ShareNotFound();
761
-		}
762
-
763
-		return $share;
764
-	}
765
-
766
-	/**
767
-	 * Get shares for a given path
768
-	 *
769
-	 * @param \OCP\Files\Node $path
770
-	 * @return IShare[]
771
-	 */
772
-	public function getSharesByPath(Node $path) {
773
-		$qb = $this->dbConnection->getQueryBuilder();
774
-
775
-		$cursor = $qb->select('*')
776
-			->from('share')
777
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
778
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
779
-			->execute();
780
-
781
-		$shares = [];
782
-		while($data = $cursor->fetch()) {
783
-			$shares[] = $this->createShareObject($data);
784
-		}
785
-		$cursor->closeCursor();
786
-
787
-		return $shares;
788
-	}
789
-
790
-	/**
791
-	 * @inheritdoc
792
-	 */
793
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
794
-		/** @var IShare[] $shares */
795
-		$shares = [];
796
-
797
-		//Get shares directly with this user
798
-		$qb = $this->dbConnection->getQueryBuilder();
799
-		$qb->select('*')
800
-			->from('share');
801
-
802
-		// Order by id
803
-		$qb->orderBy('id');
804
-
805
-		// Set limit and offset
806
-		if ($limit !== -1) {
807
-			$qb->setMaxResults($limit);
808
-		}
809
-		$qb->setFirstResult($offset);
810
-
811
-		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
812
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
813
-
814
-		// Filter by node if provided
815
-		if ($node !== null) {
816
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
817
-		}
818
-
819
-		$cursor = $qb->execute();
820
-
821
-		while($data = $cursor->fetch()) {
822
-			$shares[] = $this->createShareObject($data);
823
-		}
824
-		$cursor->closeCursor();
825
-
826
-
827
-		return $shares;
828
-	}
829
-
830
-	/**
831
-	 * Get a share by token
832
-	 *
833
-	 * @param string $token
834
-	 * @return IShare
835
-	 * @throws ShareNotFound
836
-	 */
837
-	public function getShareByToken($token) {
838
-		$qb = $this->dbConnection->getQueryBuilder();
839
-
840
-		$cursor = $qb->select('*')
841
-			->from('share')
842
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
843
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
844
-			->execute();
845
-
846
-		$data = $cursor->fetch();
847
-
848
-		if ($data === false) {
849
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
850
-		}
851
-
852
-		try {
853
-			$share = $this->createShareObject($data);
854
-		} catch (InvalidShare $e) {
855
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
856
-		}
857
-
858
-		return $share;
859
-	}
860
-
861
-	/**
862
-	 * remove share from table
863
-	 *
864
-	 * @param string $shareId
865
-	 */
866
-	protected function removeShareFromTable($shareId) {
867
-		$qb = $this->dbConnection->getQueryBuilder();
868
-		$qb->delete('share')
869
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
870
-		$qb->execute();
871
-	}
872
-
873
-	/**
874
-	 * Create a share object from an database row
875
-	 *
876
-	 * @param array $data
877
-	 * @return IShare
878
-	 * @throws InvalidShare
879
-	 * @throws ShareNotFound
880
-	 */
881
-	protected function createShareObject($data) {
882
-
883
-		$share = new Share($this->rootFolder, $this->userManager);
884
-		$share->setId((int)$data['id'])
885
-			->setShareType((int)$data['share_type'])
886
-			->setPermissions((int)$data['permissions'])
887
-			->setTarget($data['file_target'])
888
-			->setMailSend((bool)$data['mail_send'])
889
-			->setToken($data['token']);
890
-
891
-		$shareTime = new \DateTime();
892
-		$shareTime->setTimestamp((int)$data['stime']);
893
-		$share->setShareTime($shareTime);
894
-		$share->setSharedWith($data['share_with']);
895
-		$share->setPassword($data['password']);
896
-
897
-		if ($data['uid_initiator'] !== null) {
898
-			$share->setShareOwner($data['uid_owner']);
899
-			$share->setSharedBy($data['uid_initiator']);
900
-		} else {
901
-			//OLD SHARE
902
-			$share->setSharedBy($data['uid_owner']);
903
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
904
-
905
-			$owner = $path->getOwner();
906
-			$share->setShareOwner($owner->getUID());
907
-		}
908
-
909
-		if ($data['expiration'] !== null) {
910
-			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
911
-			if ($expiration !== false) {
912
-				$share->setExpirationDate($expiration);
913
-			}
914
-		}
915
-
916
-		$share->setNodeId((int)$data['file_source']);
917
-		$share->setNodeType($data['item_type']);
918
-
919
-		$share->setProviderId($this->identifier());
920
-
921
-		return $share;
922
-	}
923
-
924
-	/**
925
-	 * Get the node with file $id for $user
926
-	 *
927
-	 * @param string $userId
928
-	 * @param int $id
929
-	 * @return \OCP\Files\File|\OCP\Files\Folder
930
-	 * @throws InvalidShare
931
-	 */
932
-	private function getNode($userId, $id) {
933
-		try {
934
-			$userFolder = $this->rootFolder->getUserFolder($userId);
935
-		} catch (NoUserException $e) {
936
-			throw new InvalidShare();
937
-		}
938
-
939
-		$nodes = $userFolder->getById($id);
940
-
941
-		if (empty($nodes)) {
942
-			throw new InvalidShare();
943
-		}
944
-
945
-		return $nodes[0];
946
-	}
947
-
948
-	/**
949
-	 * A user is deleted from the system
950
-	 * So clean up the relevant shares.
951
-	 *
952
-	 * @param string $uid
953
-	 * @param int $shareType
954
-	 */
955
-	public function userDeleted($uid, $shareType) {
956
-		$qb = $this->dbConnection->getQueryBuilder();
957
-
958
-		$qb->delete('share')
959
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
960
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
961
-			->execute();
962
-	}
963
-
964
-	/**
965
-	 * This provider does not support group shares
966
-	 *
967
-	 * @param string $gid
968
-	 */
969
-	public function groupDeleted($gid) {
970
-		return;
971
-	}
972
-
973
-	/**
974
-	 * This provider does not support group shares
975
-	 *
976
-	 * @param string $uid
977
-	 * @param string $gid
978
-	 */
979
-	public function userDeletedFromGroup($uid, $gid) {
980
-		return;
981
-	}
982
-
983
-	/**
984
-	 * get database row of a give share
985
-	 *
986
-	 * @param $id
987
-	 * @return array
988
-	 * @throws ShareNotFound
989
-	 */
990
-	protected function getRawShare($id) {
991
-
992
-		// Now fetch the inserted share and create a complete share object
993
-		$qb = $this->dbConnection->getQueryBuilder();
994
-		$qb->select('*')
995
-			->from('share')
996
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
997
-
998
-		$cursor = $qb->execute();
999
-		$data = $cursor->fetch();
1000
-		$cursor->closeCursor();
1001
-
1002
-		if ($data === false) {
1003
-			throw new ShareNotFound;
1004
-		}
1005
-
1006
-		return $data;
1007
-	}
1008
-
1009
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
1010
-		$qb = $this->dbConnection->getQueryBuilder();
1011
-		$qb->select('*')
1012
-			->from('share', 's')
1013
-			->andWhere($qb->expr()->orX(
1014
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1015
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1016
-			))
1017
-			->andWhere(
1018
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
1019
-			);
1020
-
1021
-		/**
1022
-		 * Reshares for this user are shares where they are the owner.
1023
-		 */
1024
-		if ($reshares === false) {
1025
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1026
-		} else {
1027
-			$qb->andWhere(
1028
-				$qb->expr()->orX(
1029
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1030
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1031
-				)
1032
-			);
1033
-		}
1034
-
1035
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1036
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1037
-
1038
-		$qb->orderBy('id');
1039
-
1040
-		$cursor = $qb->execute();
1041
-		$shares = [];
1042
-		while ($data = $cursor->fetch()) {
1043
-			$shares[$data['fileid']][] = $this->createShareObject($data);
1044
-		}
1045
-		$cursor->closeCursor();
1046
-
1047
-		return $shares;
1048
-	}
1049
-
1050
-	/**
1051
-	 * @inheritdoc
1052
-	 */
1053
-	public function getAccessList($nodes, $currentAccess) {
1054
-		$ids = [];
1055
-		foreach ($nodes as $node) {
1056
-			$ids[] = $node->getId();
1057
-		}
1058
-
1059
-		$qb = $this->dbConnection->getQueryBuilder();
1060
-		$qb->select('share_with')
1061
-			->from('share')
1062
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
1063
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1064
-			->andWhere($qb->expr()->orX(
1065
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1066
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1067
-			))
1068
-			->setMaxResults(1);
1069
-		$cursor = $qb->execute();
1070
-
1071
-		$mail = $cursor->fetch() !== false;
1072
-		$cursor->closeCursor();
1073
-
1074
-		return ['public' => $mail];
1075
-	}
642
+        $qb = $this->dbConnection->getQueryBuilder();
643
+        $qb->update('share')
644
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
645
+            ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
646
+            ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
647
+            ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
648
+            ->set('password', $qb->createNamedParameter($share->getPassword()))
649
+            ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
650
+            ->execute();
651
+
652
+        return $share;
653
+    }
654
+
655
+    /**
656
+     * @inheritdoc
657
+     */
658
+    public function move(IShare $share, $recipient) {
659
+        /**
660
+         * nothing to do here, mail shares are only outgoing shares
661
+         */
662
+        return $share;
663
+    }
664
+
665
+    /**
666
+     * Delete a share (owner unShares the file)
667
+     *
668
+     * @param IShare $share
669
+     */
670
+    public function delete(IShare $share) {
671
+        $this->removeShareFromTable($share->getId());
672
+    }
673
+
674
+    /**
675
+     * @inheritdoc
676
+     */
677
+    public function deleteFromSelf(IShare $share, $recipient) {
678
+        // nothing to do here, mail shares are only outgoing shares
679
+        return;
680
+    }
681
+
682
+    /**
683
+     * @inheritdoc
684
+     */
685
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
686
+        $qb = $this->dbConnection->getQueryBuilder();
687
+        $qb->select('*')
688
+            ->from('share');
689
+
690
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
691
+
692
+        /**
693
+         * Reshares for this user are shares where they are the owner.
694
+         */
695
+        if ($reshares === false) {
696
+            //Special case for old shares created via the web UI
697
+            $or1 = $qb->expr()->andX(
698
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
699
+                $qb->expr()->isNull('uid_initiator')
700
+            );
701
+
702
+            $qb->andWhere(
703
+                $qb->expr()->orX(
704
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
705
+                    $or1
706
+                )
707
+            );
708
+        } else {
709
+            $qb->andWhere(
710
+                $qb->expr()->orX(
711
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
712
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
713
+                )
714
+            );
715
+        }
716
+
717
+        if ($node !== null) {
718
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
719
+        }
720
+
721
+        if ($limit !== -1) {
722
+            $qb->setMaxResults($limit);
723
+        }
724
+
725
+        $qb->setFirstResult($offset);
726
+        $qb->orderBy('id');
727
+
728
+        $cursor = $qb->execute();
729
+        $shares = [];
730
+        while($data = $cursor->fetch()) {
731
+            $shares[] = $this->createShareObject($data);
732
+        }
733
+        $cursor->closeCursor();
734
+
735
+        return $shares;
736
+    }
737
+
738
+    /**
739
+     * @inheritdoc
740
+     */
741
+    public function getShareById($id, $recipientId = null) {
742
+        $qb = $this->dbConnection->getQueryBuilder();
743
+
744
+        $qb->select('*')
745
+            ->from('share')
746
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
747
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
748
+
749
+        $cursor = $qb->execute();
750
+        $data = $cursor->fetch();
751
+        $cursor->closeCursor();
752
+
753
+        if ($data === false) {
754
+            throw new ShareNotFound();
755
+        }
756
+
757
+        try {
758
+            $share = $this->createShareObject($data);
759
+        } catch (InvalidShare $e) {
760
+            throw new ShareNotFound();
761
+        }
762
+
763
+        return $share;
764
+    }
765
+
766
+    /**
767
+     * Get shares for a given path
768
+     *
769
+     * @param \OCP\Files\Node $path
770
+     * @return IShare[]
771
+     */
772
+    public function getSharesByPath(Node $path) {
773
+        $qb = $this->dbConnection->getQueryBuilder();
774
+
775
+        $cursor = $qb->select('*')
776
+            ->from('share')
777
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
778
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
779
+            ->execute();
780
+
781
+        $shares = [];
782
+        while($data = $cursor->fetch()) {
783
+            $shares[] = $this->createShareObject($data);
784
+        }
785
+        $cursor->closeCursor();
786
+
787
+        return $shares;
788
+    }
789
+
790
+    /**
791
+     * @inheritdoc
792
+     */
793
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
794
+        /** @var IShare[] $shares */
795
+        $shares = [];
796
+
797
+        //Get shares directly with this user
798
+        $qb = $this->dbConnection->getQueryBuilder();
799
+        $qb->select('*')
800
+            ->from('share');
801
+
802
+        // Order by id
803
+        $qb->orderBy('id');
804
+
805
+        // Set limit and offset
806
+        if ($limit !== -1) {
807
+            $qb->setMaxResults($limit);
808
+        }
809
+        $qb->setFirstResult($offset);
810
+
811
+        $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
812
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
813
+
814
+        // Filter by node if provided
815
+        if ($node !== null) {
816
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
817
+        }
818
+
819
+        $cursor = $qb->execute();
820
+
821
+        while($data = $cursor->fetch()) {
822
+            $shares[] = $this->createShareObject($data);
823
+        }
824
+        $cursor->closeCursor();
825
+
826
+
827
+        return $shares;
828
+    }
829
+
830
+    /**
831
+     * Get a share by token
832
+     *
833
+     * @param string $token
834
+     * @return IShare
835
+     * @throws ShareNotFound
836
+     */
837
+    public function getShareByToken($token) {
838
+        $qb = $this->dbConnection->getQueryBuilder();
839
+
840
+        $cursor = $qb->select('*')
841
+            ->from('share')
842
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
843
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
844
+            ->execute();
845
+
846
+        $data = $cursor->fetch();
847
+
848
+        if ($data === false) {
849
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
850
+        }
851
+
852
+        try {
853
+            $share = $this->createShareObject($data);
854
+        } catch (InvalidShare $e) {
855
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
856
+        }
857
+
858
+        return $share;
859
+    }
860
+
861
+    /**
862
+     * remove share from table
863
+     *
864
+     * @param string $shareId
865
+     */
866
+    protected function removeShareFromTable($shareId) {
867
+        $qb = $this->dbConnection->getQueryBuilder();
868
+        $qb->delete('share')
869
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
870
+        $qb->execute();
871
+    }
872
+
873
+    /**
874
+     * Create a share object from an database row
875
+     *
876
+     * @param array $data
877
+     * @return IShare
878
+     * @throws InvalidShare
879
+     * @throws ShareNotFound
880
+     */
881
+    protected function createShareObject($data) {
882
+
883
+        $share = new Share($this->rootFolder, $this->userManager);
884
+        $share->setId((int)$data['id'])
885
+            ->setShareType((int)$data['share_type'])
886
+            ->setPermissions((int)$data['permissions'])
887
+            ->setTarget($data['file_target'])
888
+            ->setMailSend((bool)$data['mail_send'])
889
+            ->setToken($data['token']);
890
+
891
+        $shareTime = new \DateTime();
892
+        $shareTime->setTimestamp((int)$data['stime']);
893
+        $share->setShareTime($shareTime);
894
+        $share->setSharedWith($data['share_with']);
895
+        $share->setPassword($data['password']);
896
+
897
+        if ($data['uid_initiator'] !== null) {
898
+            $share->setShareOwner($data['uid_owner']);
899
+            $share->setSharedBy($data['uid_initiator']);
900
+        } else {
901
+            //OLD SHARE
902
+            $share->setSharedBy($data['uid_owner']);
903
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
904
+
905
+            $owner = $path->getOwner();
906
+            $share->setShareOwner($owner->getUID());
907
+        }
908
+
909
+        if ($data['expiration'] !== null) {
910
+            $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
911
+            if ($expiration !== false) {
912
+                $share->setExpirationDate($expiration);
913
+            }
914
+        }
915
+
916
+        $share->setNodeId((int)$data['file_source']);
917
+        $share->setNodeType($data['item_type']);
918
+
919
+        $share->setProviderId($this->identifier());
920
+
921
+        return $share;
922
+    }
923
+
924
+    /**
925
+     * Get the node with file $id for $user
926
+     *
927
+     * @param string $userId
928
+     * @param int $id
929
+     * @return \OCP\Files\File|\OCP\Files\Folder
930
+     * @throws InvalidShare
931
+     */
932
+    private function getNode($userId, $id) {
933
+        try {
934
+            $userFolder = $this->rootFolder->getUserFolder($userId);
935
+        } catch (NoUserException $e) {
936
+            throw new InvalidShare();
937
+        }
938
+
939
+        $nodes = $userFolder->getById($id);
940
+
941
+        if (empty($nodes)) {
942
+            throw new InvalidShare();
943
+        }
944
+
945
+        return $nodes[0];
946
+    }
947
+
948
+    /**
949
+     * A user is deleted from the system
950
+     * So clean up the relevant shares.
951
+     *
952
+     * @param string $uid
953
+     * @param int $shareType
954
+     */
955
+    public function userDeleted($uid, $shareType) {
956
+        $qb = $this->dbConnection->getQueryBuilder();
957
+
958
+        $qb->delete('share')
959
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
960
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
961
+            ->execute();
962
+    }
963
+
964
+    /**
965
+     * This provider does not support group shares
966
+     *
967
+     * @param string $gid
968
+     */
969
+    public function groupDeleted($gid) {
970
+        return;
971
+    }
972
+
973
+    /**
974
+     * This provider does not support group shares
975
+     *
976
+     * @param string $uid
977
+     * @param string $gid
978
+     */
979
+    public function userDeletedFromGroup($uid, $gid) {
980
+        return;
981
+    }
982
+
983
+    /**
984
+     * get database row of a give share
985
+     *
986
+     * @param $id
987
+     * @return array
988
+     * @throws ShareNotFound
989
+     */
990
+    protected function getRawShare($id) {
991
+
992
+        // Now fetch the inserted share and create a complete share object
993
+        $qb = $this->dbConnection->getQueryBuilder();
994
+        $qb->select('*')
995
+            ->from('share')
996
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
997
+
998
+        $cursor = $qb->execute();
999
+        $data = $cursor->fetch();
1000
+        $cursor->closeCursor();
1001
+
1002
+        if ($data === false) {
1003
+            throw new ShareNotFound;
1004
+        }
1005
+
1006
+        return $data;
1007
+    }
1008
+
1009
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
1010
+        $qb = $this->dbConnection->getQueryBuilder();
1011
+        $qb->select('*')
1012
+            ->from('share', 's')
1013
+            ->andWhere($qb->expr()->orX(
1014
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1015
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1016
+            ))
1017
+            ->andWhere(
1018
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
1019
+            );
1020
+
1021
+        /**
1022
+         * Reshares for this user are shares where they are the owner.
1023
+         */
1024
+        if ($reshares === false) {
1025
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1026
+        } else {
1027
+            $qb->andWhere(
1028
+                $qb->expr()->orX(
1029
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1030
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1031
+                )
1032
+            );
1033
+        }
1034
+
1035
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1036
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1037
+
1038
+        $qb->orderBy('id');
1039
+
1040
+        $cursor = $qb->execute();
1041
+        $shares = [];
1042
+        while ($data = $cursor->fetch()) {
1043
+            $shares[$data['fileid']][] = $this->createShareObject($data);
1044
+        }
1045
+        $cursor->closeCursor();
1046
+
1047
+        return $shares;
1048
+    }
1049
+
1050
+    /**
1051
+     * @inheritdoc
1052
+     */
1053
+    public function getAccessList($nodes, $currentAccess) {
1054
+        $ids = [];
1055
+        foreach ($nodes as $node) {
1056
+            $ids[] = $node->getId();
1057
+        }
1058
+
1059
+        $qb = $this->dbConnection->getQueryBuilder();
1060
+        $qb->select('share_with')
1061
+            ->from('share')
1062
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
1063
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1064
+            ->andWhere($qb->expr()->orX(
1065
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1066
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1067
+            ))
1068
+            ->setMaxResults(1);
1069
+        $cursor = $qb->execute();
1070
+
1071
+        $mail = $cursor->fetch() !== false;
1072
+        $cursor->closeCursor();
1073
+
1074
+        return ['public' => $mail];
1075
+    }
1076 1076
 
1077 1077
 }
Please login to merge, or discard this patch.
Spacing   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -210,10 +210,10 @@  discard block
 block discarded – undo
210 210
 		}
211 211
 
212 212
 		$passwordPolicy = $this->getPasswordPolicy();
213
-		$passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS;
213
+		$passwordCharset = ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_DIGITS;
214 214
 		$passwordLength = 8;
215 215
 		if (!empty($passwordPolicy)) {
216
-			$passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength;
216
+			$passwordLength = (int) $passwordPolicy['minLength'] > 0 ? (int) $passwordPolicy['minLength'] : $passwordLength;
217 217
 			$passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : '';
218 218
 		}
219 219
 
@@ -351,11 +351,11 @@  discard block
 block discarded – undo
351 351
 				$share->getExpirationDate()
352 352
 			);
353 353
 		} catch (HintException $hintException) {
354
-			$this->logger->error('Failed to send share by mail: ' . $hintException->getMessage());
354
+			$this->logger->error('Failed to send share by mail: '.$hintException->getMessage());
355 355
 			$this->removeShareFromTable($shareId);
356 356
 			throw $hintException;
357 357
 		} catch (\Exception $e) {
358
-			$this->logger->error('Failed to send share by email: ' . $e->getMessage());
358
+			$this->logger->error('Failed to send share by email: '.$e->getMessage());
359 359
 			$this->removeShareFromTable($shareId);
360 360
 			throw new HintException('Failed to send share by mail',
361 361
 				$this->l->t('Failed to send share by email'));
@@ -380,7 +380,7 @@  discard block
 block discarded – undo
380 380
 											\DateTime $expiration = null) {
381 381
 		$initiatorUser = $this->userManager->get($initiator);
382 382
 		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
383
-		$subject = (string)$this->l->t('%s shared »%s« with you', array($initiatorDisplayName, $filename));
383
+		$subject = (string) $this->l->t('%s shared »%s« with you', array($initiatorDisplayName, $filename));
384 384
 
385 385
 		$message = $this->mailer->createMessage();
386 386
 
@@ -397,7 +397,7 @@  discard block
 block discarded – undo
397 397
 		$text = $this->l->t('%s shared »%s« with you.', [$initiatorDisplayName, $filename]);
398 398
 
399 399
 		$emailTemplate->addBodyText(
400
-			$text . ' ' . $this->l->t('Click the button below to open it.'),
400
+			$text.' '.$this->l->t('Click the button below to open it.'),
401 401
 			$text
402 402
 		);
403 403
 		$emailTemplate->addBodyButton(
@@ -421,9 +421,9 @@  discard block
 block discarded – undo
421 421
 		// The "Reply-To" is set to the sharer if an mail address is configured
422 422
 		// also the default footer contains a "Do not reply" which needs to be adjusted.
423 423
 		$initiatorEmail = $initiatorUser->getEMailAddress();
424
-		if($initiatorEmail !== null) {
424
+		if ($initiatorEmail !== null) {
425 425
 			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
426
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
426
+			$emailTemplate->addFooter($instanceName.' - '.$this->defaults->getSlogan());
427 427
 		} else {
428 428
 			$emailTemplate->addFooter();
429 429
 		}
@@ -455,7 +455,7 @@  discard block
 block discarded – undo
455 455
 		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
456 456
 		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
457 457
 
458
-		$subject = (string)$this->l->t('Password to access »%s« shared to you by %s', [$filename, $initiatorDisplayName]);
458
+		$subject = (string) $this->l->t('Password to access »%s« shared to you by %s', [$filename, $initiatorDisplayName]);
459 459
 		$plainBodyPart = $this->l->t("%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]);
460 460
 		$htmlBodyPart = $this->l->t('%s shared »%s« with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
461 461
 
@@ -479,7 +479,7 @@  discard block
 block discarded – undo
479 479
 		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
480 480
 		if ($initiatorEmailAddress !== null) {
481 481
 			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
482
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
482
+			$emailTemplate->addFooter($instanceName.' - '.$this->defaults->getSlogan());
483 483
 		} else {
484 484
 			$emailTemplate->addFooter();
485 485
 		}
@@ -518,7 +518,7 @@  discard block
 block discarded – undo
518 518
 			);
519 519
 		}
520 520
 
521
-		$subject = (string)$this->l->t('Password to access »%s« shared with %s', [$filename, $shareWith]);
521
+		$subject = (string) $this->l->t('Password to access »%s« shared with %s', [$filename, $shareWith]);
522 522
 		$bodyPart = $this->l->t("You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %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()]);
523 523
 
524 524
 		$message = $this->mailer->createMessage();
@@ -572,7 +572,7 @@  discard block
 block discarded – undo
572 572
 			->orderBy('id');
573 573
 
574 574
 		$cursor = $qb->execute();
575
-		while($data = $cursor->fetch()) {
575
+		while ($data = $cursor->fetch()) {
576 576
 			$children[] = $this->createShareObject($data);
577 577
 		}
578 578
 		$cursor->closeCursor();
@@ -616,7 +616,7 @@  discard block
 block discarded – undo
616 616
 		$qb->execute();
617 617
 		$id = $qb->getLastInsertId();
618 618
 
619
-		return (int)$id;
619
+		return (int) $id;
620 620
 	}
621 621
 
622 622
 	/**
@@ -633,7 +633,7 @@  discard block
 block discarded – undo
633 633
 		// a real password was given
634 634
 		$validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
635 635
 
636
-		if($validPassword && $originalShare->getPassword() !== $share->getPassword()) {
636
+		if ($validPassword && $originalShare->getPassword() !== $share->getPassword()) {
637 637
 			$this->sendPassword($share, $plainTextPassword);
638 638
 		}
639 639
 		/*
@@ -727,7 +727,7 @@  discard block
 block discarded – undo
727 727
 
728 728
 		$cursor = $qb->execute();
729 729
 		$shares = [];
730
-		while($data = $cursor->fetch()) {
730
+		while ($data = $cursor->fetch()) {
731 731
 			$shares[] = $this->createShareObject($data);
732 732
 		}
733 733
 		$cursor->closeCursor();
@@ -779,7 +779,7 @@  discard block
 block discarded – undo
779 779
 			->execute();
780 780
 
781 781
 		$shares = [];
782
-		while($data = $cursor->fetch()) {
782
+		while ($data = $cursor->fetch()) {
783 783
 			$shares[] = $this->createShareObject($data);
784 784
 		}
785 785
 		$cursor->closeCursor();
@@ -818,7 +818,7 @@  discard block
 block discarded – undo
818 818
 
819 819
 		$cursor = $qb->execute();
820 820
 
821
-		while($data = $cursor->fetch()) {
821
+		while ($data = $cursor->fetch()) {
822 822
 			$shares[] = $this->createShareObject($data);
823 823
 		}
824 824
 		$cursor->closeCursor();
@@ -881,15 +881,15 @@  discard block
 block discarded – undo
881 881
 	protected function createShareObject($data) {
882 882
 
883 883
 		$share = new Share($this->rootFolder, $this->userManager);
884
-		$share->setId((int)$data['id'])
885
-			->setShareType((int)$data['share_type'])
886
-			->setPermissions((int)$data['permissions'])
884
+		$share->setId((int) $data['id'])
885
+			->setShareType((int) $data['share_type'])
886
+			->setPermissions((int) $data['permissions'])
887 887
 			->setTarget($data['file_target'])
888
-			->setMailSend((bool)$data['mail_send'])
888
+			->setMailSend((bool) $data['mail_send'])
889 889
 			->setToken($data['token']);
890 890
 
891 891
 		$shareTime = new \DateTime();
892
-		$shareTime->setTimestamp((int)$data['stime']);
892
+		$shareTime->setTimestamp((int) $data['stime']);
893 893
 		$share->setShareTime($shareTime);
894 894
 		$share->setSharedWith($data['share_with']);
895 895
 		$share->setPassword($data['password']);
@@ -900,7 +900,7 @@  discard block
 block discarded – undo
900 900
 		} else {
901 901
 			//OLD SHARE
902 902
 			$share->setSharedBy($data['uid_owner']);
903
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
903
+			$path = $this->getNode($share->getSharedBy(), (int) $data['file_source']);
904 904
 
905 905
 			$owner = $path->getOwner();
906 906
 			$share->setShareOwner($owner->getUID());
@@ -913,7 +913,7 @@  discard block
 block discarded – undo
913 913
 			}
914 914
 		}
915 915
 
916
-		$share->setNodeId((int)$data['file_source']);
916
+		$share->setNodeId((int) $data['file_source']);
917 917
 		$share->setNodeType($data['item_type']);
918 918
 
919 919
 		$share->setProviderId($this->identifier());
@@ -1032,7 +1032,7 @@  discard block
 block discarded – undo
1032 1032
 			);
1033 1033
 		}
1034 1034
 
1035
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1035
+		$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1036 1036
 		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1037 1037
 
1038 1038
 		$qb->orderBy('id');
Please login to merge, or discard this patch.
lib/private/Share20/Manager.php 2 patches
Indentation   +1446 added lines, -1446 removed lines patch added patch discarded remove patch
@@ -60,1474 +60,1474 @@
 block discarded – undo
60 60
  */
61 61
 class Manager implements IManager {
62 62
 
63
-	/** @var IProviderFactory */
64
-	private $factory;
65
-	/** @var ILogger */
66
-	private $logger;
67
-	/** @var IConfig */
68
-	private $config;
69
-	/** @var ISecureRandom */
70
-	private $secureRandom;
71
-	/** @var IHasher */
72
-	private $hasher;
73
-	/** @var IMountManager */
74
-	private $mountManager;
75
-	/** @var IGroupManager */
76
-	private $groupManager;
77
-	/** @var IL10N */
78
-	private $l;
79
-	/** @var IUserManager */
80
-	private $userManager;
81
-	/** @var IRootFolder */
82
-	private $rootFolder;
83
-	/** @var CappedMemoryCache */
84
-	private $sharingDisabledForUsersCache;
85
-	/** @var EventDispatcher */
86
-	private $eventDispatcher;
87
-	/** @var LegacyHooks */
88
-	private $legacyHooks;
89
-	/** @var IMailer */
90
-	private $mailer;
91
-	/** @var IURLGenerator */
92
-	private $urlGenerator;
93
-	/** @var \OC_Defaults */
94
-	private $defaults;
95
-
96
-
97
-	/**
98
-	 * Manager constructor.
99
-	 *
100
-	 * @param ILogger $logger
101
-	 * @param IConfig $config
102
-	 * @param ISecureRandom $secureRandom
103
-	 * @param IHasher $hasher
104
-	 * @param IMountManager $mountManager
105
-	 * @param IGroupManager $groupManager
106
-	 * @param IL10N $l
107
-	 * @param IProviderFactory $factory
108
-	 * @param IUserManager $userManager
109
-	 * @param IRootFolder $rootFolder
110
-	 * @param EventDispatcher $eventDispatcher
111
-	 * @param IMailer $mailer
112
-	 * @param IURLGenerator $urlGenerator
113
-	 * @param \OC_Defaults $defaults
114
-	 */
115
-	public function __construct(
116
-			ILogger $logger,
117
-			IConfig $config,
118
-			ISecureRandom $secureRandom,
119
-			IHasher $hasher,
120
-			IMountManager $mountManager,
121
-			IGroupManager $groupManager,
122
-			IL10N $l,
123
-			IProviderFactory $factory,
124
-			IUserManager $userManager,
125
-			IRootFolder $rootFolder,
126
-			EventDispatcher $eventDispatcher,
127
-			IMailer $mailer,
128
-			IURLGenerator $urlGenerator,
129
-			\OC_Defaults $defaults
130
-	) {
131
-		$this->logger = $logger;
132
-		$this->config = $config;
133
-		$this->secureRandom = $secureRandom;
134
-		$this->hasher = $hasher;
135
-		$this->mountManager = $mountManager;
136
-		$this->groupManager = $groupManager;
137
-		$this->l = $l;
138
-		$this->factory = $factory;
139
-		$this->userManager = $userManager;
140
-		$this->rootFolder = $rootFolder;
141
-		$this->eventDispatcher = $eventDispatcher;
142
-		$this->sharingDisabledForUsersCache = new CappedMemoryCache();
143
-		$this->legacyHooks = new LegacyHooks($this->eventDispatcher);
144
-		$this->mailer = $mailer;
145
-		$this->urlGenerator = $urlGenerator;
146
-		$this->defaults = $defaults;
147
-	}
148
-
149
-	/**
150
-	 * Convert from a full share id to a tuple (providerId, shareId)
151
-	 *
152
-	 * @param string $id
153
-	 * @return string[]
154
-	 */
155
-	private function splitFullId($id) {
156
-		return explode(':', $id, 2);
157
-	}
158
-
159
-	/**
160
-	 * Verify if a password meets all requirements
161
-	 *
162
-	 * @param string $password
163
-	 * @throws \Exception
164
-	 */
165
-	protected function verifyPassword($password) {
166
-		if ($password === null) {
167
-			// No password is set, check if this is allowed.
168
-			if ($this->shareApiLinkEnforcePassword()) {
169
-				throw new \InvalidArgumentException('Passwords are enforced for link shares');
170
-			}
171
-
172
-			return;
173
-		}
174
-
175
-		// Let others verify the password
176
-		try {
177
-			$event = new GenericEvent($password);
178
-			$this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event);
179
-		} catch (HintException $e) {
180
-			throw new \Exception($e->getHint());
181
-		}
182
-	}
183
-
184
-	/**
185
-	 * Check for generic requirements before creating a share
186
-	 *
187
-	 * @param \OCP\Share\IShare $share
188
-	 * @throws \InvalidArgumentException
189
-	 * @throws GenericShareException
190
-	 *
191
-	 * @suppress PhanUndeclaredClassMethod
192
-	 */
193
-	protected function generalCreateChecks(\OCP\Share\IShare $share) {
194
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
195
-			// We expect a valid user as sharedWith for user shares
196
-			if (!$this->userManager->userExists($share->getSharedWith())) {
197
-				throw new \InvalidArgumentException('SharedWith is not a valid user');
198
-			}
199
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
200
-			// We expect a valid group as sharedWith for group shares
201
-			if (!$this->groupManager->groupExists($share->getSharedWith())) {
202
-				throw new \InvalidArgumentException('SharedWith is not a valid group');
203
-			}
204
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
205
-			if ($share->getSharedWith() !== null) {
206
-				throw new \InvalidArgumentException('SharedWith should be empty');
207
-			}
208
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
209
-			if ($share->getSharedWith() === null) {
210
-				throw new \InvalidArgumentException('SharedWith should not be empty');
211
-			}
212
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
213
-			if ($share->getSharedWith() === null) {
214
-				throw new \InvalidArgumentException('SharedWith should not be empty');
215
-			}
216
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) {
217
-			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($share->getSharedWith());
218
-			if ($circle === null) {
219
-				throw new \InvalidArgumentException('SharedWith is not a valid circle');
220
-			}
221
-		} else {
222
-			// We can't handle other types yet
223
-			throw new \InvalidArgumentException('unknown share type');
224
-		}
225
-
226
-		// Verify the initiator of the share is set
227
-		if ($share->getSharedBy() === null) {
228
-			throw new \InvalidArgumentException('SharedBy should be set');
229
-		}
230
-
231
-		// Cannot share with yourself
232
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
233
-			$share->getSharedWith() === $share->getSharedBy()) {
234
-			throw new \InvalidArgumentException('Can’t share with yourself');
235
-		}
236
-
237
-		// The path should be set
238
-		if ($share->getNode() === null) {
239
-			throw new \InvalidArgumentException('Path should be set');
240
-		}
241
-
242
-		// And it should be a file or a folder
243
-		if (!($share->getNode() instanceof \OCP\Files\File) &&
244
-				!($share->getNode() instanceof \OCP\Files\Folder)) {
245
-			throw new \InvalidArgumentException('Path should be either a file or a folder');
246
-		}
247
-
248
-		// And you can't share your rootfolder
249
-		if ($this->userManager->userExists($share->getSharedBy())) {
250
-			$sharedPath = $this->rootFolder->getUserFolder($share->getSharedBy())->getPath();
251
-		} else {
252
-			$sharedPath = $this->rootFolder->getUserFolder($share->getShareOwner())->getPath();
253
-		}
254
-		if ($sharedPath === $share->getNode()->getPath()) {
255
-			throw new \InvalidArgumentException('You can’t share your root folder');
256
-		}
257
-
258
-		// Check if we actually have share permissions
259
-		if (!$share->getNode()->isShareable()) {
260
-			$message_t = $this->l->t('You are not allowed to share %s', [$share->getNode()->getPath()]);
261
-			throw new GenericShareException($message_t, $message_t, 404);
262
-		}
263
-
264
-		// Permissions should be set
265
-		if ($share->getPermissions() === null) {
266
-			throw new \InvalidArgumentException('A share requires permissions');
267
-		}
268
-
269
-		/*
63
+    /** @var IProviderFactory */
64
+    private $factory;
65
+    /** @var ILogger */
66
+    private $logger;
67
+    /** @var IConfig */
68
+    private $config;
69
+    /** @var ISecureRandom */
70
+    private $secureRandom;
71
+    /** @var IHasher */
72
+    private $hasher;
73
+    /** @var IMountManager */
74
+    private $mountManager;
75
+    /** @var IGroupManager */
76
+    private $groupManager;
77
+    /** @var IL10N */
78
+    private $l;
79
+    /** @var IUserManager */
80
+    private $userManager;
81
+    /** @var IRootFolder */
82
+    private $rootFolder;
83
+    /** @var CappedMemoryCache */
84
+    private $sharingDisabledForUsersCache;
85
+    /** @var EventDispatcher */
86
+    private $eventDispatcher;
87
+    /** @var LegacyHooks */
88
+    private $legacyHooks;
89
+    /** @var IMailer */
90
+    private $mailer;
91
+    /** @var IURLGenerator */
92
+    private $urlGenerator;
93
+    /** @var \OC_Defaults */
94
+    private $defaults;
95
+
96
+
97
+    /**
98
+     * Manager constructor.
99
+     *
100
+     * @param ILogger $logger
101
+     * @param IConfig $config
102
+     * @param ISecureRandom $secureRandom
103
+     * @param IHasher $hasher
104
+     * @param IMountManager $mountManager
105
+     * @param IGroupManager $groupManager
106
+     * @param IL10N $l
107
+     * @param IProviderFactory $factory
108
+     * @param IUserManager $userManager
109
+     * @param IRootFolder $rootFolder
110
+     * @param EventDispatcher $eventDispatcher
111
+     * @param IMailer $mailer
112
+     * @param IURLGenerator $urlGenerator
113
+     * @param \OC_Defaults $defaults
114
+     */
115
+    public function __construct(
116
+            ILogger $logger,
117
+            IConfig $config,
118
+            ISecureRandom $secureRandom,
119
+            IHasher $hasher,
120
+            IMountManager $mountManager,
121
+            IGroupManager $groupManager,
122
+            IL10N $l,
123
+            IProviderFactory $factory,
124
+            IUserManager $userManager,
125
+            IRootFolder $rootFolder,
126
+            EventDispatcher $eventDispatcher,
127
+            IMailer $mailer,
128
+            IURLGenerator $urlGenerator,
129
+            \OC_Defaults $defaults
130
+    ) {
131
+        $this->logger = $logger;
132
+        $this->config = $config;
133
+        $this->secureRandom = $secureRandom;
134
+        $this->hasher = $hasher;
135
+        $this->mountManager = $mountManager;
136
+        $this->groupManager = $groupManager;
137
+        $this->l = $l;
138
+        $this->factory = $factory;
139
+        $this->userManager = $userManager;
140
+        $this->rootFolder = $rootFolder;
141
+        $this->eventDispatcher = $eventDispatcher;
142
+        $this->sharingDisabledForUsersCache = new CappedMemoryCache();
143
+        $this->legacyHooks = new LegacyHooks($this->eventDispatcher);
144
+        $this->mailer = $mailer;
145
+        $this->urlGenerator = $urlGenerator;
146
+        $this->defaults = $defaults;
147
+    }
148
+
149
+    /**
150
+     * Convert from a full share id to a tuple (providerId, shareId)
151
+     *
152
+     * @param string $id
153
+     * @return string[]
154
+     */
155
+    private function splitFullId($id) {
156
+        return explode(':', $id, 2);
157
+    }
158
+
159
+    /**
160
+     * Verify if a password meets all requirements
161
+     *
162
+     * @param string $password
163
+     * @throws \Exception
164
+     */
165
+    protected function verifyPassword($password) {
166
+        if ($password === null) {
167
+            // No password is set, check if this is allowed.
168
+            if ($this->shareApiLinkEnforcePassword()) {
169
+                throw new \InvalidArgumentException('Passwords are enforced for link shares');
170
+            }
171
+
172
+            return;
173
+        }
174
+
175
+        // Let others verify the password
176
+        try {
177
+            $event = new GenericEvent($password);
178
+            $this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event);
179
+        } catch (HintException $e) {
180
+            throw new \Exception($e->getHint());
181
+        }
182
+    }
183
+
184
+    /**
185
+     * Check for generic requirements before creating a share
186
+     *
187
+     * @param \OCP\Share\IShare $share
188
+     * @throws \InvalidArgumentException
189
+     * @throws GenericShareException
190
+     *
191
+     * @suppress PhanUndeclaredClassMethod
192
+     */
193
+    protected function generalCreateChecks(\OCP\Share\IShare $share) {
194
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
195
+            // We expect a valid user as sharedWith for user shares
196
+            if (!$this->userManager->userExists($share->getSharedWith())) {
197
+                throw new \InvalidArgumentException('SharedWith is not a valid user');
198
+            }
199
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
200
+            // We expect a valid group as sharedWith for group shares
201
+            if (!$this->groupManager->groupExists($share->getSharedWith())) {
202
+                throw new \InvalidArgumentException('SharedWith is not a valid group');
203
+            }
204
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
205
+            if ($share->getSharedWith() !== null) {
206
+                throw new \InvalidArgumentException('SharedWith should be empty');
207
+            }
208
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
209
+            if ($share->getSharedWith() === null) {
210
+                throw new \InvalidArgumentException('SharedWith should not be empty');
211
+            }
212
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
213
+            if ($share->getSharedWith() === null) {
214
+                throw new \InvalidArgumentException('SharedWith should not be empty');
215
+            }
216
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) {
217
+            $circle = \OCA\Circles\Api\v1\Circles::detailsCircle($share->getSharedWith());
218
+            if ($circle === null) {
219
+                throw new \InvalidArgumentException('SharedWith is not a valid circle');
220
+            }
221
+        } else {
222
+            // We can't handle other types yet
223
+            throw new \InvalidArgumentException('unknown share type');
224
+        }
225
+
226
+        // Verify the initiator of the share is set
227
+        if ($share->getSharedBy() === null) {
228
+            throw new \InvalidArgumentException('SharedBy should be set');
229
+        }
230
+
231
+        // Cannot share with yourself
232
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
233
+            $share->getSharedWith() === $share->getSharedBy()) {
234
+            throw new \InvalidArgumentException('Can’t share with yourself');
235
+        }
236
+
237
+        // The path should be set
238
+        if ($share->getNode() === null) {
239
+            throw new \InvalidArgumentException('Path should be set');
240
+        }
241
+
242
+        // And it should be a file or a folder
243
+        if (!($share->getNode() instanceof \OCP\Files\File) &&
244
+                !($share->getNode() instanceof \OCP\Files\Folder)) {
245
+            throw new \InvalidArgumentException('Path should be either a file or a folder');
246
+        }
247
+
248
+        // And you can't share your rootfolder
249
+        if ($this->userManager->userExists($share->getSharedBy())) {
250
+            $sharedPath = $this->rootFolder->getUserFolder($share->getSharedBy())->getPath();
251
+        } else {
252
+            $sharedPath = $this->rootFolder->getUserFolder($share->getShareOwner())->getPath();
253
+        }
254
+        if ($sharedPath === $share->getNode()->getPath()) {
255
+            throw new \InvalidArgumentException('You can’t share your root folder');
256
+        }
257
+
258
+        // Check if we actually have share permissions
259
+        if (!$share->getNode()->isShareable()) {
260
+            $message_t = $this->l->t('You are not allowed to share %s', [$share->getNode()->getPath()]);
261
+            throw new GenericShareException($message_t, $message_t, 404);
262
+        }
263
+
264
+        // Permissions should be set
265
+        if ($share->getPermissions() === null) {
266
+            throw new \InvalidArgumentException('A share requires permissions');
267
+        }
268
+
269
+        /*
270 270
 		 * Quick fix for #23536
271 271
 		 * Non moveable mount points do not have update and delete permissions
272 272
 		 * while we 'most likely' do have that on the storage.
273 273
 		 */
274
-		$permissions = $share->getNode()->getPermissions();
275
-		$mount = $share->getNode()->getMountPoint();
276
-		if (!($mount instanceof MoveableMount)) {
277
-			$permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
278
-		}
279
-
280
-		// Check that we do not share with more permissions than we have
281
-		if ($share->getPermissions() & ~$permissions) {
282
-			$message_t = $this->l->t('Can’t increase permissions of %s', [$share->getNode()->getPath()]);
283
-			throw new GenericShareException($message_t, $message_t, 404);
284
-		}
285
-
286
-
287
-		// Check that read permissions are always set
288
-		// Link shares are allowed to have no read permissions to allow upload to hidden folders
289
-		$noReadPermissionRequired = $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK
290
-			|| $share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL;
291
-		if (!$noReadPermissionRequired &&
292
-			($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
293
-			throw new \InvalidArgumentException('Shares need at least read permissions');
294
-		}
295
-
296
-		if ($share->getNode() instanceof \OCP\Files\File) {
297
-			if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
298
-				$message_t = $this->l->t('Files can’t be shared with delete permissions');
299
-				throw new GenericShareException($message_t);
300
-			}
301
-			if ($share->getPermissions() & \OCP\Constants::PERMISSION_CREATE) {
302
-				$message_t = $this->l->t('Files can’t be shared with create permissions');
303
-				throw new GenericShareException($message_t);
304
-			}
305
-		}
306
-	}
307
-
308
-	/**
309
-	 * Validate if the expiration date fits the system settings
310
-	 *
311
-	 * @param \OCP\Share\IShare $share The share to validate the expiration date of
312
-	 * @return \OCP\Share\IShare The modified share object
313
-	 * @throws GenericShareException
314
-	 * @throws \InvalidArgumentException
315
-	 * @throws \Exception
316
-	 */
317
-	protected function validateExpirationDate(\OCP\Share\IShare $share) {
318
-
319
-		$expirationDate = $share->getExpirationDate();
320
-
321
-		if ($expirationDate !== null) {
322
-			//Make sure the expiration date is a date
323
-			$expirationDate->setTime(0, 0, 0);
324
-
325
-			$date = new \DateTime();
326
-			$date->setTime(0, 0, 0);
327
-			if ($date >= $expirationDate) {
328
-				$message = $this->l->t('Expiration date is in the past');
329
-				throw new GenericShareException($message, $message, 404);
330
-			}
331
-		}
332
-
333
-		// If expiredate is empty set a default one if there is a default
334
-		$fullId = null;
335
-		try {
336
-			$fullId = $share->getFullId();
337
-		} catch (\UnexpectedValueException $e) {
338
-			// This is a new share
339
-		}
340
-
341
-		if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
342
-			$expirationDate = new \DateTime();
343
-			$expirationDate->setTime(0,0,0);
344
-			$expirationDate->add(new \DateInterval('P'.$this->shareApiLinkDefaultExpireDays().'D'));
345
-		}
346
-
347
-		// If we enforce the expiration date check that is does not exceed
348
-		if ($this->shareApiLinkDefaultExpireDateEnforced()) {
349
-			if ($expirationDate === null) {
350
-				throw new \InvalidArgumentException('Expiration date is enforced');
351
-			}
352
-
353
-			$date = new \DateTime();
354
-			$date->setTime(0, 0, 0);
355
-			$date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
356
-			if ($date < $expirationDate) {
357
-				$message = $this->l->t('Can’t set expiration date more than %s days in the future', [$this->shareApiLinkDefaultExpireDays()]);
358
-				throw new GenericShareException($message, $message, 404);
359
-			}
360
-		}
361
-
362
-		$accepted = true;
363
-		$message = '';
364
-		\OCP\Util::emitHook('\OC\Share', 'verifyExpirationDate', [
365
-			'expirationDate' => &$expirationDate,
366
-			'accepted' => &$accepted,
367
-			'message' => &$message,
368
-			'passwordSet' => $share->getPassword() !== null,
369
-		]);
370
-
371
-		if (!$accepted) {
372
-			throw new \Exception($message);
373
-		}
374
-
375
-		$share->setExpirationDate($expirationDate);
376
-
377
-		return $share;
378
-	}
379
-
380
-	/**
381
-	 * Check for pre share requirements for user shares
382
-	 *
383
-	 * @param \OCP\Share\IShare $share
384
-	 * @throws \Exception
385
-	 */
386
-	protected function userCreateChecks(\OCP\Share\IShare $share) {
387
-		// Check if we can share with group members only
388
-		if ($this->shareWithGroupMembersOnly()) {
389
-			$sharedBy = $this->userManager->get($share->getSharedBy());
390
-			$sharedWith = $this->userManager->get($share->getSharedWith());
391
-			// Verify we can share with this user
392
-			$groups = array_intersect(
393
-					$this->groupManager->getUserGroupIds($sharedBy),
394
-					$this->groupManager->getUserGroupIds($sharedWith)
395
-			);
396
-			if (empty($groups)) {
397
-				throw new \Exception('Sharing is only allowed with group members');
398
-			}
399
-		}
400
-
401
-		/*
274
+        $permissions = $share->getNode()->getPermissions();
275
+        $mount = $share->getNode()->getMountPoint();
276
+        if (!($mount instanceof MoveableMount)) {
277
+            $permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
278
+        }
279
+
280
+        // Check that we do not share with more permissions than we have
281
+        if ($share->getPermissions() & ~$permissions) {
282
+            $message_t = $this->l->t('Can’t increase permissions of %s', [$share->getNode()->getPath()]);
283
+            throw new GenericShareException($message_t, $message_t, 404);
284
+        }
285
+
286
+
287
+        // Check that read permissions are always set
288
+        // Link shares are allowed to have no read permissions to allow upload to hidden folders
289
+        $noReadPermissionRequired = $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK
290
+            || $share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL;
291
+        if (!$noReadPermissionRequired &&
292
+            ($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
293
+            throw new \InvalidArgumentException('Shares need at least read permissions');
294
+        }
295
+
296
+        if ($share->getNode() instanceof \OCP\Files\File) {
297
+            if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
298
+                $message_t = $this->l->t('Files can’t be shared with delete permissions');
299
+                throw new GenericShareException($message_t);
300
+            }
301
+            if ($share->getPermissions() & \OCP\Constants::PERMISSION_CREATE) {
302
+                $message_t = $this->l->t('Files can’t be shared with create permissions');
303
+                throw new GenericShareException($message_t);
304
+            }
305
+        }
306
+    }
307
+
308
+    /**
309
+     * Validate if the expiration date fits the system settings
310
+     *
311
+     * @param \OCP\Share\IShare $share The share to validate the expiration date of
312
+     * @return \OCP\Share\IShare The modified share object
313
+     * @throws GenericShareException
314
+     * @throws \InvalidArgumentException
315
+     * @throws \Exception
316
+     */
317
+    protected function validateExpirationDate(\OCP\Share\IShare $share) {
318
+
319
+        $expirationDate = $share->getExpirationDate();
320
+
321
+        if ($expirationDate !== null) {
322
+            //Make sure the expiration date is a date
323
+            $expirationDate->setTime(0, 0, 0);
324
+
325
+            $date = new \DateTime();
326
+            $date->setTime(0, 0, 0);
327
+            if ($date >= $expirationDate) {
328
+                $message = $this->l->t('Expiration date is in the past');
329
+                throw new GenericShareException($message, $message, 404);
330
+            }
331
+        }
332
+
333
+        // If expiredate is empty set a default one if there is a default
334
+        $fullId = null;
335
+        try {
336
+            $fullId = $share->getFullId();
337
+        } catch (\UnexpectedValueException $e) {
338
+            // This is a new share
339
+        }
340
+
341
+        if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
342
+            $expirationDate = new \DateTime();
343
+            $expirationDate->setTime(0,0,0);
344
+            $expirationDate->add(new \DateInterval('P'.$this->shareApiLinkDefaultExpireDays().'D'));
345
+        }
346
+
347
+        // If we enforce the expiration date check that is does not exceed
348
+        if ($this->shareApiLinkDefaultExpireDateEnforced()) {
349
+            if ($expirationDate === null) {
350
+                throw new \InvalidArgumentException('Expiration date is enforced');
351
+            }
352
+
353
+            $date = new \DateTime();
354
+            $date->setTime(0, 0, 0);
355
+            $date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
356
+            if ($date < $expirationDate) {
357
+                $message = $this->l->t('Can’t set expiration date more than %s days in the future', [$this->shareApiLinkDefaultExpireDays()]);
358
+                throw new GenericShareException($message, $message, 404);
359
+            }
360
+        }
361
+
362
+        $accepted = true;
363
+        $message = '';
364
+        \OCP\Util::emitHook('\OC\Share', 'verifyExpirationDate', [
365
+            'expirationDate' => &$expirationDate,
366
+            'accepted' => &$accepted,
367
+            'message' => &$message,
368
+            'passwordSet' => $share->getPassword() !== null,
369
+        ]);
370
+
371
+        if (!$accepted) {
372
+            throw new \Exception($message);
373
+        }
374
+
375
+        $share->setExpirationDate($expirationDate);
376
+
377
+        return $share;
378
+    }
379
+
380
+    /**
381
+     * Check for pre share requirements for user shares
382
+     *
383
+     * @param \OCP\Share\IShare $share
384
+     * @throws \Exception
385
+     */
386
+    protected function userCreateChecks(\OCP\Share\IShare $share) {
387
+        // Check if we can share with group members only
388
+        if ($this->shareWithGroupMembersOnly()) {
389
+            $sharedBy = $this->userManager->get($share->getSharedBy());
390
+            $sharedWith = $this->userManager->get($share->getSharedWith());
391
+            // Verify we can share with this user
392
+            $groups = array_intersect(
393
+                    $this->groupManager->getUserGroupIds($sharedBy),
394
+                    $this->groupManager->getUserGroupIds($sharedWith)
395
+            );
396
+            if (empty($groups)) {
397
+                throw new \Exception('Sharing is only allowed with group members');
398
+            }
399
+        }
400
+
401
+        /*
402 402
 		 * TODO: Could be costly, fix
403 403
 		 *
404 404
 		 * Also this is not what we want in the future.. then we want to squash identical shares.
405 405
 		 */
406
-		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_USER);
407
-		$existingShares = $provider->getSharesByPath($share->getNode());
408
-		foreach($existingShares as $existingShare) {
409
-			// Ignore if it is the same share
410
-			try {
411
-				if ($existingShare->getFullId() === $share->getFullId()) {
412
-					continue;
413
-				}
414
-			} catch (\UnexpectedValueException $e) {
415
-				//Shares are not identical
416
-			}
417
-
418
-			// Identical share already existst
419
-			if ($existingShare->getSharedWith() === $share->getSharedWith()) {
420
-				throw new \Exception('Path is already shared with this user');
421
-			}
422
-
423
-			// The share is already shared with this user via a group share
424
-			if ($existingShare->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
425
-				$group = $this->groupManager->get($existingShare->getSharedWith());
426
-				if (!is_null($group)) {
427
-					$user = $this->userManager->get($share->getSharedWith());
428
-
429
-					if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
430
-						throw new \Exception('Path is already shared with this user');
431
-					}
432
-				}
433
-			}
434
-		}
435
-	}
436
-
437
-	/**
438
-	 * Check for pre share requirements for group shares
439
-	 *
440
-	 * @param \OCP\Share\IShare $share
441
-	 * @throws \Exception
442
-	 */
443
-	protected function groupCreateChecks(\OCP\Share\IShare $share) {
444
-		// Verify group shares are allowed
445
-		if (!$this->allowGroupSharing()) {
446
-			throw new \Exception('Group sharing is now allowed');
447
-		}
448
-
449
-		// Verify if the user can share with this group
450
-		if ($this->shareWithGroupMembersOnly()) {
451
-			$sharedBy = $this->userManager->get($share->getSharedBy());
452
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
453
-			if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
454
-				throw new \Exception('Sharing is only allowed within your own groups');
455
-			}
456
-		}
457
-
458
-		/*
406
+        $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_USER);
407
+        $existingShares = $provider->getSharesByPath($share->getNode());
408
+        foreach($existingShares as $existingShare) {
409
+            // Ignore if it is the same share
410
+            try {
411
+                if ($existingShare->getFullId() === $share->getFullId()) {
412
+                    continue;
413
+                }
414
+            } catch (\UnexpectedValueException $e) {
415
+                //Shares are not identical
416
+            }
417
+
418
+            // Identical share already existst
419
+            if ($existingShare->getSharedWith() === $share->getSharedWith()) {
420
+                throw new \Exception('Path is already shared with this user');
421
+            }
422
+
423
+            // The share is already shared with this user via a group share
424
+            if ($existingShare->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
425
+                $group = $this->groupManager->get($existingShare->getSharedWith());
426
+                if (!is_null($group)) {
427
+                    $user = $this->userManager->get($share->getSharedWith());
428
+
429
+                    if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
430
+                        throw new \Exception('Path is already shared with this user');
431
+                    }
432
+                }
433
+            }
434
+        }
435
+    }
436
+
437
+    /**
438
+     * Check for pre share requirements for group shares
439
+     *
440
+     * @param \OCP\Share\IShare $share
441
+     * @throws \Exception
442
+     */
443
+    protected function groupCreateChecks(\OCP\Share\IShare $share) {
444
+        // Verify group shares are allowed
445
+        if (!$this->allowGroupSharing()) {
446
+            throw new \Exception('Group sharing is now allowed');
447
+        }
448
+
449
+        // Verify if the user can share with this group
450
+        if ($this->shareWithGroupMembersOnly()) {
451
+            $sharedBy = $this->userManager->get($share->getSharedBy());
452
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
453
+            if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
454
+                throw new \Exception('Sharing is only allowed within your own groups');
455
+            }
456
+        }
457
+
458
+        /*
459 459
 		 * TODO: Could be costly, fix
460 460
 		 *
461 461
 		 * Also this is not what we want in the future.. then we want to squash identical shares.
462 462
 		 */
463
-		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
464
-		$existingShares = $provider->getSharesByPath($share->getNode());
465
-		foreach($existingShares as $existingShare) {
466
-			try {
467
-				if ($existingShare->getFullId() === $share->getFullId()) {
468
-					continue;
469
-				}
470
-			} catch (\UnexpectedValueException $e) {
471
-				//It is a new share so just continue
472
-			}
473
-
474
-			if ($existingShare->getSharedWith() === $share->getSharedWith()) {
475
-				throw new \Exception('Path is already shared with this group');
476
-			}
477
-		}
478
-	}
479
-
480
-	/**
481
-	 * Check for pre share requirements for link shares
482
-	 *
483
-	 * @param \OCP\Share\IShare $share
484
-	 * @throws \Exception
485
-	 */
486
-	protected function linkCreateChecks(\OCP\Share\IShare $share) {
487
-		// Are link shares allowed?
488
-		if (!$this->shareApiAllowLinks()) {
489
-			throw new \Exception('Link sharing is not allowed');
490
-		}
491
-
492
-		// Link shares by definition can't have share permissions
493
-		if ($share->getPermissions() & \OCP\Constants::PERMISSION_SHARE) {
494
-			throw new \InvalidArgumentException('Link shares can’t have reshare permissions');
495
-		}
496
-
497
-		// Check if public upload is allowed
498
-		if (!$this->shareApiLinkAllowPublicUpload() &&
499
-			($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) {
500
-			throw new \InvalidArgumentException('Public upload is not allowed');
501
-		}
502
-	}
503
-
504
-	/**
505
-	 * To make sure we don't get invisible link shares we set the parent
506
-	 * of a link if it is a reshare. This is a quick word around
507
-	 * until we can properly display multiple link shares in the UI
508
-	 *
509
-	 * See: https://github.com/owncloud/core/issues/22295
510
-	 *
511
-	 * FIXME: Remove once multiple link shares can be properly displayed
512
-	 *
513
-	 * @param \OCP\Share\IShare $share
514
-	 */
515
-	protected function setLinkParent(\OCP\Share\IShare $share) {
516
-
517
-		// No sense in checking if the method is not there.
518
-		if (method_exists($share, 'setParent')) {
519
-			$storage = $share->getNode()->getStorage();
520
-			if ($storage->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
521
-				/** @var \OCA\Files_Sharing\SharedStorage $storage */
522
-				$share->setParent($storage->getShareId());
523
-			}
524
-		};
525
-	}
526
-
527
-	/**
528
-	 * @param File|Folder $path
529
-	 */
530
-	protected function pathCreateChecks($path) {
531
-		// Make sure that we do not share a path that contains a shared mountpoint
532
-		if ($path instanceof \OCP\Files\Folder) {
533
-			$mounts = $this->mountManager->findIn($path->getPath());
534
-			foreach($mounts as $mount) {
535
-				if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
536
-					throw new \InvalidArgumentException('Path contains files shared with you');
537
-				}
538
-			}
539
-		}
540
-	}
541
-
542
-	/**
543
-	 * Check if the user that is sharing can actually share
544
-	 *
545
-	 * @param \OCP\Share\IShare $share
546
-	 * @throws \Exception
547
-	 */
548
-	protected function canShare(\OCP\Share\IShare $share) {
549
-		if (!$this->shareApiEnabled()) {
550
-			throw new \Exception('Sharing is disabled');
551
-		}
552
-
553
-		if ($this->sharingDisabledForUser($share->getSharedBy())) {
554
-			throw new \Exception('Sharing is disabled for you');
555
-		}
556
-	}
557
-
558
-	/**
559
-	 * Share a path
560
-	 *
561
-	 * @param \OCP\Share\IShare $share
562
-	 * @return Share The share object
563
-	 * @throws \Exception
564
-	 *
565
-	 * TODO: handle link share permissions or check them
566
-	 */
567
-	public function createShare(\OCP\Share\IShare $share) {
568
-		$this->canShare($share);
569
-
570
-		$this->generalCreateChecks($share);
571
-
572
-		// Verify if there are any issues with the path
573
-		$this->pathCreateChecks($share->getNode());
574
-
575
-		/*
463
+        $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
464
+        $existingShares = $provider->getSharesByPath($share->getNode());
465
+        foreach($existingShares as $existingShare) {
466
+            try {
467
+                if ($existingShare->getFullId() === $share->getFullId()) {
468
+                    continue;
469
+                }
470
+            } catch (\UnexpectedValueException $e) {
471
+                //It is a new share so just continue
472
+            }
473
+
474
+            if ($existingShare->getSharedWith() === $share->getSharedWith()) {
475
+                throw new \Exception('Path is already shared with this group');
476
+            }
477
+        }
478
+    }
479
+
480
+    /**
481
+     * Check for pre share requirements for link shares
482
+     *
483
+     * @param \OCP\Share\IShare $share
484
+     * @throws \Exception
485
+     */
486
+    protected function linkCreateChecks(\OCP\Share\IShare $share) {
487
+        // Are link shares allowed?
488
+        if (!$this->shareApiAllowLinks()) {
489
+            throw new \Exception('Link sharing is not allowed');
490
+        }
491
+
492
+        // Link shares by definition can't have share permissions
493
+        if ($share->getPermissions() & \OCP\Constants::PERMISSION_SHARE) {
494
+            throw new \InvalidArgumentException('Link shares can’t have reshare permissions');
495
+        }
496
+
497
+        // Check if public upload is allowed
498
+        if (!$this->shareApiLinkAllowPublicUpload() &&
499
+            ($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) {
500
+            throw new \InvalidArgumentException('Public upload is not allowed');
501
+        }
502
+    }
503
+
504
+    /**
505
+     * To make sure we don't get invisible link shares we set the parent
506
+     * of a link if it is a reshare. This is a quick word around
507
+     * until we can properly display multiple link shares in the UI
508
+     *
509
+     * See: https://github.com/owncloud/core/issues/22295
510
+     *
511
+     * FIXME: Remove once multiple link shares can be properly displayed
512
+     *
513
+     * @param \OCP\Share\IShare $share
514
+     */
515
+    protected function setLinkParent(\OCP\Share\IShare $share) {
516
+
517
+        // No sense in checking if the method is not there.
518
+        if (method_exists($share, 'setParent')) {
519
+            $storage = $share->getNode()->getStorage();
520
+            if ($storage->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
521
+                /** @var \OCA\Files_Sharing\SharedStorage $storage */
522
+                $share->setParent($storage->getShareId());
523
+            }
524
+        };
525
+    }
526
+
527
+    /**
528
+     * @param File|Folder $path
529
+     */
530
+    protected function pathCreateChecks($path) {
531
+        // Make sure that we do not share a path that contains a shared mountpoint
532
+        if ($path instanceof \OCP\Files\Folder) {
533
+            $mounts = $this->mountManager->findIn($path->getPath());
534
+            foreach($mounts as $mount) {
535
+                if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
536
+                    throw new \InvalidArgumentException('Path contains files shared with you');
537
+                }
538
+            }
539
+        }
540
+    }
541
+
542
+    /**
543
+     * Check if the user that is sharing can actually share
544
+     *
545
+     * @param \OCP\Share\IShare $share
546
+     * @throws \Exception
547
+     */
548
+    protected function canShare(\OCP\Share\IShare $share) {
549
+        if (!$this->shareApiEnabled()) {
550
+            throw new \Exception('Sharing is disabled');
551
+        }
552
+
553
+        if ($this->sharingDisabledForUser($share->getSharedBy())) {
554
+            throw new \Exception('Sharing is disabled for you');
555
+        }
556
+    }
557
+
558
+    /**
559
+     * Share a path
560
+     *
561
+     * @param \OCP\Share\IShare $share
562
+     * @return Share The share object
563
+     * @throws \Exception
564
+     *
565
+     * TODO: handle link share permissions or check them
566
+     */
567
+    public function createShare(\OCP\Share\IShare $share) {
568
+        $this->canShare($share);
569
+
570
+        $this->generalCreateChecks($share);
571
+
572
+        // Verify if there are any issues with the path
573
+        $this->pathCreateChecks($share->getNode());
574
+
575
+        /*
576 576
 		 * On creation of a share the owner is always the owner of the path
577 577
 		 * Except for mounted federated shares.
578 578
 		 */
579
-		$storage = $share->getNode()->getStorage();
580
-		if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
581
-			$parent = $share->getNode()->getParent();
582
-			while($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
583
-				$parent = $parent->getParent();
584
-			}
585
-			$share->setShareOwner($parent->getOwner()->getUID());
586
-		} else {
587
-			$share->setShareOwner($share->getNode()->getOwner()->getUID());
588
-		}
589
-
590
-		//Verify share type
591
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
592
-			$this->userCreateChecks($share);
593
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
594
-			$this->groupCreateChecks($share);
595
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
596
-			$this->linkCreateChecks($share);
597
-			$this->setLinkParent($share);
598
-
599
-			/*
579
+        $storage = $share->getNode()->getStorage();
580
+        if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
581
+            $parent = $share->getNode()->getParent();
582
+            while($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
583
+                $parent = $parent->getParent();
584
+            }
585
+            $share->setShareOwner($parent->getOwner()->getUID());
586
+        } else {
587
+            $share->setShareOwner($share->getNode()->getOwner()->getUID());
588
+        }
589
+
590
+        //Verify share type
591
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
592
+            $this->userCreateChecks($share);
593
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
594
+            $this->groupCreateChecks($share);
595
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
596
+            $this->linkCreateChecks($share);
597
+            $this->setLinkParent($share);
598
+
599
+            /*
600 600
 			 * For now ignore a set token.
601 601
 			 */
602
-			$share->setToken(
603
-				$this->secureRandom->generate(
604
-					\OC\Share\Constants::TOKEN_LENGTH,
605
-					\OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
606
-				)
607
-			);
608
-
609
-			//Verify the expiration date
610
-			$this->validateExpirationDate($share);
611
-
612
-			//Verify the password
613
-			$this->verifyPassword($share->getPassword());
614
-
615
-			// If a password is set. Hash it!
616
-			if ($share->getPassword() !== null) {
617
-				$share->setPassword($this->hasher->hash($share->getPassword()));
618
-			}
619
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
620
-			$share->setToken(
621
-				$this->secureRandom->generate(
622
-					\OC\Share\Constants::TOKEN_LENGTH,
623
-					\OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
624
-				)
625
-			);
626
-		}
627
-
628
-		// Cannot share with the owner
629
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
630
-			$share->getSharedWith() === $share->getShareOwner()) {
631
-			throw new \InvalidArgumentException('Can’t share with the share owner');
632
-		}
633
-
634
-		// Generate the target
635
-		$target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getNode()->getName();
636
-		$target = \OC\Files\Filesystem::normalizePath($target);
637
-		$share->setTarget($target);
638
-
639
-		// Pre share event
640
-		$event = new GenericEvent($share);
641
-		$a = $this->eventDispatcher->dispatch('OCP\Share::preShare', $event);
642
-		if ($event->isPropagationStopped() && $event->hasArgument('error')) {
643
-			throw new \Exception($event->getArgument('error'));
644
-		}
645
-
646
-		$oldShare = $share;
647
-		$provider = $this->factory->getProviderForType($share->getShareType());
648
-		$share = $provider->create($share);
649
-		//reuse the node we already have
650
-		$share->setNode($oldShare->getNode());
651
-
652
-		// Post share event
653
-		$event = new GenericEvent($share);
654
-		$this->eventDispatcher->dispatch('OCP\Share::postShare', $event);
655
-
656
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
657
-			$user = $this->userManager->get($share->getSharedWith());
658
-			if ($user !== null) {
659
-				$emailAddress = $user->getEMailAddress();
660
-				if ($emailAddress !== null && $emailAddress !== '') {
661
-					$this->sendMailNotification(
662
-						$share->getNode()->getName(),
663
-						$this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', [ 'fileid' => $share->getNode()->getId() ]),
664
-						$share->getSharedBy(),
665
-						$emailAddress,
666
-						$share->getExpirationDate()
667
-					);
668
-					$this->logger->debug('Send share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']);
669
-				} else {
670
-					$this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']);
671
-				}
672
-			} else {
673
-				$this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']);
674
-			}
675
-		}
676
-
677
-		return $share;
678
-	}
679
-
680
-	/**
681
-	 * @param string $filename file/folder name
682
-	 * @param string $link link to the file/folder
683
-	 * @param string $initiator user ID of share sender
684
-	 * @param string $shareWith email address of share receiver
685
-	 * @param \DateTime|null $expiration
686
-	 * @throws \Exception If mail couldn't be sent
687
-	 */
688
-	protected function sendMailNotification($filename,
689
-											$link,
690
-											$initiator,
691
-											$shareWith,
692
-											\DateTime $expiration = null) {
693
-		$initiatorUser = $this->userManager->get($initiator);
694
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
695
-		$subject = (string)$this->l->t('%s shared »%s« with you', array($initiatorDisplayName, $filename));
696
-
697
-		$message = $this->mailer->createMessage();
698
-
699
-		$emailTemplate = $this->mailer->createEMailTemplate();
700
-		$emailTemplate->setMetaData('files_sharing.RecipientNotification', [
701
-			'filename' => $filename,
702
-			'link' => $link,
703
-			'initiator' => $initiatorDisplayName,
704
-			'expiration' => $expiration,
705
-		]);
706
-
707
-		$emailTemplate->addHeader();
708
-		$emailTemplate->addHeading($this->l->t('%s shared »%s« with you', [$initiatorDisplayName, $filename]), false);
709
-		$text = $this->l->t('%s shared »%s« with you.', [$initiatorDisplayName, $filename]);
710
-
711
-		$emailTemplate->addBodyText(
712
-			$text . ' ' . $this->l->t('Click the button below to open it.'),
713
-			$text
714
-		);
715
-		$emailTemplate->addBodyButton(
716
-			$this->l->t('Open »%s«', [$filename]),
717
-			$link
718
-		);
719
-
720
-		$message->setTo([$shareWith]);
721
-
722
-		// The "From" contains the sharers name
723
-		$instanceName = $this->defaults->getName();
724
-		$senderName = $this->l->t(
725
-			'%s via %s',
726
-			[
727
-				$initiatorDisplayName,
728
-				$instanceName
729
-			]
730
-		);
731
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
732
-
733
-		// The "Reply-To" is set to the sharer if an mail address is configured
734
-		// also the default footer contains a "Do not reply" which needs to be adjusted.
735
-		$initiatorEmail = $initiatorUser->getEMailAddress();
736
-		if($initiatorEmail !== null) {
737
-			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
738
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
739
-		} else {
740
-			$emailTemplate->addFooter();
741
-		}
742
-
743
-		$message->setSubject($subject);
744
-		$message->setPlainBody($emailTemplate->renderText());
745
-		$message->setHtmlBody($emailTemplate->renderHtml());
746
-		$this->mailer->send($message);
747
-	}
748
-
749
-	/**
750
-	 * Update a share
751
-	 *
752
-	 * @param \OCP\Share\IShare $share
753
-	 * @return \OCP\Share\IShare The share object
754
-	 * @throws \InvalidArgumentException
755
-	 */
756
-	public function updateShare(\OCP\Share\IShare $share) {
757
-		$expirationDateUpdated = false;
758
-
759
-		$this->canShare($share);
760
-
761
-		try {
762
-			$originalShare = $this->getShareById($share->getFullId());
763
-		} catch (\UnexpectedValueException $e) {
764
-			throw new \InvalidArgumentException('Share does not have a full id');
765
-		}
766
-
767
-		// We can't change the share type!
768
-		if ($share->getShareType() !== $originalShare->getShareType()) {
769
-			throw new \InvalidArgumentException('Can’t change share type');
770
-		}
771
-
772
-		// We can only change the recipient on user shares
773
-		if ($share->getSharedWith() !== $originalShare->getSharedWith() &&
774
-		    $share->getShareType() !== \OCP\Share::SHARE_TYPE_USER) {
775
-			throw new \InvalidArgumentException('Can only update recipient on user shares');
776
-		}
777
-
778
-		// Cannot share with the owner
779
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
780
-			$share->getSharedWith() === $share->getShareOwner()) {
781
-			throw new \InvalidArgumentException('Can’t share with the share owner');
782
-		}
783
-
784
-		$this->generalCreateChecks($share);
785
-
786
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
787
-			$this->userCreateChecks($share);
788
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
789
-			$this->groupCreateChecks($share);
790
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
791
-			$this->linkCreateChecks($share);
792
-
793
-			$this->updateSharePasswordIfNeeded($share, $originalShare);
794
-
795
-			if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
796
-				//Verify the expiration date
797
-				$this->validateExpirationDate($share);
798
-				$expirationDateUpdated = true;
799
-			}
800
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
801
-			$plainTextPassword = $share->getPassword();
802
-			if (!$this->updateSharePasswordIfNeeded($share, $originalShare)) {
803
-				$plainTextPassword = null;
804
-			}
805
-		}
806
-
807
-		$this->pathCreateChecks($share->getNode());
808
-
809
-		// Now update the share!
810
-		$provider = $this->factory->getProviderForType($share->getShareType());
811
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
812
-			$share = $provider->update($share, $plainTextPassword);
813
-		} else {
814
-			$share = $provider->update($share);
815
-		}
816
-
817
-		if ($expirationDateUpdated === true) {
818
-			\OC_Hook::emit('OCP\Share', 'post_set_expiration_date', [
819
-				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
820
-				'itemSource' => $share->getNode()->getId(),
821
-				'date' => $share->getExpirationDate(),
822
-				'uidOwner' => $share->getSharedBy(),
823
-			]);
824
-		}
825
-
826
-		if ($share->getPassword() !== $originalShare->getPassword()) {
827
-			\OC_Hook::emit('OCP\Share', 'post_update_password', [
828
-				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
829
-				'itemSource' => $share->getNode()->getId(),
830
-				'uidOwner' => $share->getSharedBy(),
831
-				'token' => $share->getToken(),
832
-				'disabled' => is_null($share->getPassword()),
833
-			]);
834
-		}
835
-
836
-		if ($share->getPermissions() !== $originalShare->getPermissions()) {
837
-			if ($this->userManager->userExists($share->getShareOwner())) {
838
-				$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
839
-			} else {
840
-				$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
841
-			}
842
-			\OC_Hook::emit('OCP\Share', 'post_update_permissions', array(
843
-				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
844
-				'itemSource' => $share->getNode()->getId(),
845
-				'shareType' => $share->getShareType(),
846
-				'shareWith' => $share->getSharedWith(),
847
-				'uidOwner' => $share->getSharedBy(),
848
-				'permissions' => $share->getPermissions(),
849
-				'path' => $userFolder->getRelativePath($share->getNode()->getPath()),
850
-			));
851
-		}
852
-
853
-		return $share;
854
-	}
855
-
856
-	/**
857
-	 * Updates the password of the given share if it is not the same as the
858
-	 * password of the original share.
859
-	 *
860
-	 * @param \OCP\Share\IShare $share the share to update its password.
861
-	 * @param \OCP\Share\IShare $originalShare the original share to compare its
862
-	 *        password with.
863
-	 * @return boolean whether the password was updated or not.
864
-	 */
865
-	private function updateSharePasswordIfNeeded(\OCP\Share\IShare $share, \OCP\Share\IShare $originalShare) {
866
-		// Password updated.
867
-		if ($share->getPassword() !== $originalShare->getPassword()) {
868
-			//Verify the password
869
-			$this->verifyPassword($share->getPassword());
870
-
871
-			// If a password is set. Hash it!
872
-			if ($share->getPassword() !== null) {
873
-				$share->setPassword($this->hasher->hash($share->getPassword()));
874
-
875
-				return true;
876
-			}
877
-		}
878
-
879
-		return false;
880
-	}
881
-
882
-	/**
883
-	 * Delete all the children of this share
884
-	 * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
885
-	 *
886
-	 * @param \OCP\Share\IShare $share
887
-	 * @return \OCP\Share\IShare[] List of deleted shares
888
-	 */
889
-	protected function deleteChildren(\OCP\Share\IShare $share) {
890
-		$deletedShares = [];
891
-
892
-		$provider = $this->factory->getProviderForType($share->getShareType());
893
-
894
-		foreach ($provider->getChildren($share) as $child) {
895
-			$deletedChildren = $this->deleteChildren($child);
896
-			$deletedShares = array_merge($deletedShares, $deletedChildren);
897
-
898
-			$provider->delete($child);
899
-			$deletedShares[] = $child;
900
-		}
901
-
902
-		return $deletedShares;
903
-	}
904
-
905
-	/**
906
-	 * Delete a share
907
-	 *
908
-	 * @param \OCP\Share\IShare $share
909
-	 * @throws ShareNotFound
910
-	 * @throws \InvalidArgumentException
911
-	 */
912
-	public function deleteShare(\OCP\Share\IShare $share) {
913
-
914
-		try {
915
-			$share->getFullId();
916
-		} catch (\UnexpectedValueException $e) {
917
-			throw new \InvalidArgumentException('Share does not have a full id');
918
-		}
919
-
920
-		$event = new GenericEvent($share);
921
-		$this->eventDispatcher->dispatch('OCP\Share::preUnshare', $event);
922
-
923
-		// Get all children and delete them as well
924
-		$deletedShares = $this->deleteChildren($share);
925
-
926
-		// Do the actual delete
927
-		$provider = $this->factory->getProviderForType($share->getShareType());
928
-		$provider->delete($share);
929
-
930
-		// All the deleted shares caused by this delete
931
-		$deletedShares[] = $share;
932
-
933
-		// Emit post hook
934
-		$event->setArgument('deletedShares', $deletedShares);
935
-		$this->eventDispatcher->dispatch('OCP\Share::postUnshare', $event);
936
-	}
937
-
938
-
939
-	/**
940
-	 * Unshare a file as the recipient.
941
-	 * This can be different from a regular delete for example when one of
942
-	 * the users in a groups deletes that share. But the provider should
943
-	 * handle this.
944
-	 *
945
-	 * @param \OCP\Share\IShare $share
946
-	 * @param string $recipientId
947
-	 */
948
-	public function deleteFromSelf(\OCP\Share\IShare $share, $recipientId) {
949
-		list($providerId, ) = $this->splitFullId($share->getFullId());
950
-		$provider = $this->factory->getProvider($providerId);
951
-
952
-		$provider->deleteFromSelf($share, $recipientId);
953
-		$event = new GenericEvent($share);
954
-		$this->eventDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event);
955
-	}
956
-
957
-	/**
958
-	 * @inheritdoc
959
-	 */
960
-	public function moveShare(\OCP\Share\IShare $share, $recipientId) {
961
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
962
-			throw new \InvalidArgumentException('Can’t change target of link share');
963
-		}
964
-
965
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() !== $recipientId) {
966
-			throw new \InvalidArgumentException('Invalid recipient');
967
-		}
968
-
969
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
970
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
971
-			if (is_null($sharedWith)) {
972
-				throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist');
973
-			}
974
-			$recipient = $this->userManager->get($recipientId);
975
-			if (!$sharedWith->inGroup($recipient)) {
976
-				throw new \InvalidArgumentException('Invalid recipient');
977
-			}
978
-		}
979
-
980
-		list($providerId, ) = $this->splitFullId($share->getFullId());
981
-		$provider = $this->factory->getProvider($providerId);
982
-
983
-		$provider->move($share, $recipientId);
984
-	}
985
-
986
-	public function getSharesInFolder($userId, Folder $node, $reshares = false) {
987
-		$providers = $this->factory->getAllProviders();
988
-
989
-		return array_reduce($providers, function($shares, IShareProvider $provider) use ($userId, $node, $reshares) {
990
-			$newShares = $provider->getSharesInFolder($userId, $node, $reshares);
991
-			foreach ($newShares as $fid => $data) {
992
-				if (!isset($shares[$fid])) {
993
-					$shares[$fid] = [];
994
-				}
995
-
996
-				$shares[$fid] = array_merge($shares[$fid], $data);
997
-			}
998
-			return $shares;
999
-		}, []);
1000
-	}
1001
-
1002
-	/**
1003
-	 * @inheritdoc
1004
-	 */
1005
-	public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0) {
1006
-		if ($path !== null &&
1007
-				!($path instanceof \OCP\Files\File) &&
1008
-				!($path instanceof \OCP\Files\Folder)) {
1009
-			throw new \InvalidArgumentException('invalid path');
1010
-		}
1011
-
1012
-		try {
1013
-			$provider = $this->factory->getProviderForType($shareType);
1014
-		} catch (ProviderException $e) {
1015
-			return [];
1016
-		}
1017
-
1018
-		$shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1019
-
1020
-		/*
602
+            $share->setToken(
603
+                $this->secureRandom->generate(
604
+                    \OC\Share\Constants::TOKEN_LENGTH,
605
+                    \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
606
+                )
607
+            );
608
+
609
+            //Verify the expiration date
610
+            $this->validateExpirationDate($share);
611
+
612
+            //Verify the password
613
+            $this->verifyPassword($share->getPassword());
614
+
615
+            // If a password is set. Hash it!
616
+            if ($share->getPassword() !== null) {
617
+                $share->setPassword($this->hasher->hash($share->getPassword()));
618
+            }
619
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
620
+            $share->setToken(
621
+                $this->secureRandom->generate(
622
+                    \OC\Share\Constants::TOKEN_LENGTH,
623
+                    \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
624
+                )
625
+            );
626
+        }
627
+
628
+        // Cannot share with the owner
629
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
630
+            $share->getSharedWith() === $share->getShareOwner()) {
631
+            throw new \InvalidArgumentException('Can’t share with the share owner');
632
+        }
633
+
634
+        // Generate the target
635
+        $target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getNode()->getName();
636
+        $target = \OC\Files\Filesystem::normalizePath($target);
637
+        $share->setTarget($target);
638
+
639
+        // Pre share event
640
+        $event = new GenericEvent($share);
641
+        $a = $this->eventDispatcher->dispatch('OCP\Share::preShare', $event);
642
+        if ($event->isPropagationStopped() && $event->hasArgument('error')) {
643
+            throw new \Exception($event->getArgument('error'));
644
+        }
645
+
646
+        $oldShare = $share;
647
+        $provider = $this->factory->getProviderForType($share->getShareType());
648
+        $share = $provider->create($share);
649
+        //reuse the node we already have
650
+        $share->setNode($oldShare->getNode());
651
+
652
+        // Post share event
653
+        $event = new GenericEvent($share);
654
+        $this->eventDispatcher->dispatch('OCP\Share::postShare', $event);
655
+
656
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
657
+            $user = $this->userManager->get($share->getSharedWith());
658
+            if ($user !== null) {
659
+                $emailAddress = $user->getEMailAddress();
660
+                if ($emailAddress !== null && $emailAddress !== '') {
661
+                    $this->sendMailNotification(
662
+                        $share->getNode()->getName(),
663
+                        $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', [ 'fileid' => $share->getNode()->getId() ]),
664
+                        $share->getSharedBy(),
665
+                        $emailAddress,
666
+                        $share->getExpirationDate()
667
+                    );
668
+                    $this->logger->debug('Send share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']);
669
+                } else {
670
+                    $this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']);
671
+                }
672
+            } else {
673
+                $this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']);
674
+            }
675
+        }
676
+
677
+        return $share;
678
+    }
679
+
680
+    /**
681
+     * @param string $filename file/folder name
682
+     * @param string $link link to the file/folder
683
+     * @param string $initiator user ID of share sender
684
+     * @param string $shareWith email address of share receiver
685
+     * @param \DateTime|null $expiration
686
+     * @throws \Exception If mail couldn't be sent
687
+     */
688
+    protected function sendMailNotification($filename,
689
+                                            $link,
690
+                                            $initiator,
691
+                                            $shareWith,
692
+                                            \DateTime $expiration = null) {
693
+        $initiatorUser = $this->userManager->get($initiator);
694
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
695
+        $subject = (string)$this->l->t('%s shared »%s« with you', array($initiatorDisplayName, $filename));
696
+
697
+        $message = $this->mailer->createMessage();
698
+
699
+        $emailTemplate = $this->mailer->createEMailTemplate();
700
+        $emailTemplate->setMetaData('files_sharing.RecipientNotification', [
701
+            'filename' => $filename,
702
+            'link' => $link,
703
+            'initiator' => $initiatorDisplayName,
704
+            'expiration' => $expiration,
705
+        ]);
706
+
707
+        $emailTemplate->addHeader();
708
+        $emailTemplate->addHeading($this->l->t('%s shared »%s« with you', [$initiatorDisplayName, $filename]), false);
709
+        $text = $this->l->t('%s shared »%s« with you.', [$initiatorDisplayName, $filename]);
710
+
711
+        $emailTemplate->addBodyText(
712
+            $text . ' ' . $this->l->t('Click the button below to open it.'),
713
+            $text
714
+        );
715
+        $emailTemplate->addBodyButton(
716
+            $this->l->t('Open »%s«', [$filename]),
717
+            $link
718
+        );
719
+
720
+        $message->setTo([$shareWith]);
721
+
722
+        // The "From" contains the sharers name
723
+        $instanceName = $this->defaults->getName();
724
+        $senderName = $this->l->t(
725
+            '%s via %s',
726
+            [
727
+                $initiatorDisplayName,
728
+                $instanceName
729
+            ]
730
+        );
731
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
732
+
733
+        // The "Reply-To" is set to the sharer if an mail address is configured
734
+        // also the default footer contains a "Do not reply" which needs to be adjusted.
735
+        $initiatorEmail = $initiatorUser->getEMailAddress();
736
+        if($initiatorEmail !== null) {
737
+            $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
738
+            $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
739
+        } else {
740
+            $emailTemplate->addFooter();
741
+        }
742
+
743
+        $message->setSubject($subject);
744
+        $message->setPlainBody($emailTemplate->renderText());
745
+        $message->setHtmlBody($emailTemplate->renderHtml());
746
+        $this->mailer->send($message);
747
+    }
748
+
749
+    /**
750
+     * Update a share
751
+     *
752
+     * @param \OCP\Share\IShare $share
753
+     * @return \OCP\Share\IShare The share object
754
+     * @throws \InvalidArgumentException
755
+     */
756
+    public function updateShare(\OCP\Share\IShare $share) {
757
+        $expirationDateUpdated = false;
758
+
759
+        $this->canShare($share);
760
+
761
+        try {
762
+            $originalShare = $this->getShareById($share->getFullId());
763
+        } catch (\UnexpectedValueException $e) {
764
+            throw new \InvalidArgumentException('Share does not have a full id');
765
+        }
766
+
767
+        // We can't change the share type!
768
+        if ($share->getShareType() !== $originalShare->getShareType()) {
769
+            throw new \InvalidArgumentException('Can’t change share type');
770
+        }
771
+
772
+        // We can only change the recipient on user shares
773
+        if ($share->getSharedWith() !== $originalShare->getSharedWith() &&
774
+            $share->getShareType() !== \OCP\Share::SHARE_TYPE_USER) {
775
+            throw new \InvalidArgumentException('Can only update recipient on user shares');
776
+        }
777
+
778
+        // Cannot share with the owner
779
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
780
+            $share->getSharedWith() === $share->getShareOwner()) {
781
+            throw new \InvalidArgumentException('Can’t share with the share owner');
782
+        }
783
+
784
+        $this->generalCreateChecks($share);
785
+
786
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
787
+            $this->userCreateChecks($share);
788
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
789
+            $this->groupCreateChecks($share);
790
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
791
+            $this->linkCreateChecks($share);
792
+
793
+            $this->updateSharePasswordIfNeeded($share, $originalShare);
794
+
795
+            if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
796
+                //Verify the expiration date
797
+                $this->validateExpirationDate($share);
798
+                $expirationDateUpdated = true;
799
+            }
800
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
801
+            $plainTextPassword = $share->getPassword();
802
+            if (!$this->updateSharePasswordIfNeeded($share, $originalShare)) {
803
+                $plainTextPassword = null;
804
+            }
805
+        }
806
+
807
+        $this->pathCreateChecks($share->getNode());
808
+
809
+        // Now update the share!
810
+        $provider = $this->factory->getProviderForType($share->getShareType());
811
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
812
+            $share = $provider->update($share, $plainTextPassword);
813
+        } else {
814
+            $share = $provider->update($share);
815
+        }
816
+
817
+        if ($expirationDateUpdated === true) {
818
+            \OC_Hook::emit('OCP\Share', 'post_set_expiration_date', [
819
+                'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
820
+                'itemSource' => $share->getNode()->getId(),
821
+                'date' => $share->getExpirationDate(),
822
+                'uidOwner' => $share->getSharedBy(),
823
+            ]);
824
+        }
825
+
826
+        if ($share->getPassword() !== $originalShare->getPassword()) {
827
+            \OC_Hook::emit('OCP\Share', 'post_update_password', [
828
+                'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
829
+                'itemSource' => $share->getNode()->getId(),
830
+                'uidOwner' => $share->getSharedBy(),
831
+                'token' => $share->getToken(),
832
+                'disabled' => is_null($share->getPassword()),
833
+            ]);
834
+        }
835
+
836
+        if ($share->getPermissions() !== $originalShare->getPermissions()) {
837
+            if ($this->userManager->userExists($share->getShareOwner())) {
838
+                $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
839
+            } else {
840
+                $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
841
+            }
842
+            \OC_Hook::emit('OCP\Share', 'post_update_permissions', array(
843
+                'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
844
+                'itemSource' => $share->getNode()->getId(),
845
+                'shareType' => $share->getShareType(),
846
+                'shareWith' => $share->getSharedWith(),
847
+                'uidOwner' => $share->getSharedBy(),
848
+                'permissions' => $share->getPermissions(),
849
+                'path' => $userFolder->getRelativePath($share->getNode()->getPath()),
850
+            ));
851
+        }
852
+
853
+        return $share;
854
+    }
855
+
856
+    /**
857
+     * Updates the password of the given share if it is not the same as the
858
+     * password of the original share.
859
+     *
860
+     * @param \OCP\Share\IShare $share the share to update its password.
861
+     * @param \OCP\Share\IShare $originalShare the original share to compare its
862
+     *        password with.
863
+     * @return boolean whether the password was updated or not.
864
+     */
865
+    private function updateSharePasswordIfNeeded(\OCP\Share\IShare $share, \OCP\Share\IShare $originalShare) {
866
+        // Password updated.
867
+        if ($share->getPassword() !== $originalShare->getPassword()) {
868
+            //Verify the password
869
+            $this->verifyPassword($share->getPassword());
870
+
871
+            // If a password is set. Hash it!
872
+            if ($share->getPassword() !== null) {
873
+                $share->setPassword($this->hasher->hash($share->getPassword()));
874
+
875
+                return true;
876
+            }
877
+        }
878
+
879
+        return false;
880
+    }
881
+
882
+    /**
883
+     * Delete all the children of this share
884
+     * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
885
+     *
886
+     * @param \OCP\Share\IShare $share
887
+     * @return \OCP\Share\IShare[] List of deleted shares
888
+     */
889
+    protected function deleteChildren(\OCP\Share\IShare $share) {
890
+        $deletedShares = [];
891
+
892
+        $provider = $this->factory->getProviderForType($share->getShareType());
893
+
894
+        foreach ($provider->getChildren($share) as $child) {
895
+            $deletedChildren = $this->deleteChildren($child);
896
+            $deletedShares = array_merge($deletedShares, $deletedChildren);
897
+
898
+            $provider->delete($child);
899
+            $deletedShares[] = $child;
900
+        }
901
+
902
+        return $deletedShares;
903
+    }
904
+
905
+    /**
906
+     * Delete a share
907
+     *
908
+     * @param \OCP\Share\IShare $share
909
+     * @throws ShareNotFound
910
+     * @throws \InvalidArgumentException
911
+     */
912
+    public function deleteShare(\OCP\Share\IShare $share) {
913
+
914
+        try {
915
+            $share->getFullId();
916
+        } catch (\UnexpectedValueException $e) {
917
+            throw new \InvalidArgumentException('Share does not have a full id');
918
+        }
919
+
920
+        $event = new GenericEvent($share);
921
+        $this->eventDispatcher->dispatch('OCP\Share::preUnshare', $event);
922
+
923
+        // Get all children and delete them as well
924
+        $deletedShares = $this->deleteChildren($share);
925
+
926
+        // Do the actual delete
927
+        $provider = $this->factory->getProviderForType($share->getShareType());
928
+        $provider->delete($share);
929
+
930
+        // All the deleted shares caused by this delete
931
+        $deletedShares[] = $share;
932
+
933
+        // Emit post hook
934
+        $event->setArgument('deletedShares', $deletedShares);
935
+        $this->eventDispatcher->dispatch('OCP\Share::postUnshare', $event);
936
+    }
937
+
938
+
939
+    /**
940
+     * Unshare a file as the recipient.
941
+     * This can be different from a regular delete for example when one of
942
+     * the users in a groups deletes that share. But the provider should
943
+     * handle this.
944
+     *
945
+     * @param \OCP\Share\IShare $share
946
+     * @param string $recipientId
947
+     */
948
+    public function deleteFromSelf(\OCP\Share\IShare $share, $recipientId) {
949
+        list($providerId, ) = $this->splitFullId($share->getFullId());
950
+        $provider = $this->factory->getProvider($providerId);
951
+
952
+        $provider->deleteFromSelf($share, $recipientId);
953
+        $event = new GenericEvent($share);
954
+        $this->eventDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event);
955
+    }
956
+
957
+    /**
958
+     * @inheritdoc
959
+     */
960
+    public function moveShare(\OCP\Share\IShare $share, $recipientId) {
961
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
962
+            throw new \InvalidArgumentException('Can’t change target of link share');
963
+        }
964
+
965
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() !== $recipientId) {
966
+            throw new \InvalidArgumentException('Invalid recipient');
967
+        }
968
+
969
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
970
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
971
+            if (is_null($sharedWith)) {
972
+                throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist');
973
+            }
974
+            $recipient = $this->userManager->get($recipientId);
975
+            if (!$sharedWith->inGroup($recipient)) {
976
+                throw new \InvalidArgumentException('Invalid recipient');
977
+            }
978
+        }
979
+
980
+        list($providerId, ) = $this->splitFullId($share->getFullId());
981
+        $provider = $this->factory->getProvider($providerId);
982
+
983
+        $provider->move($share, $recipientId);
984
+    }
985
+
986
+    public function getSharesInFolder($userId, Folder $node, $reshares = false) {
987
+        $providers = $this->factory->getAllProviders();
988
+
989
+        return array_reduce($providers, function($shares, IShareProvider $provider) use ($userId, $node, $reshares) {
990
+            $newShares = $provider->getSharesInFolder($userId, $node, $reshares);
991
+            foreach ($newShares as $fid => $data) {
992
+                if (!isset($shares[$fid])) {
993
+                    $shares[$fid] = [];
994
+                }
995
+
996
+                $shares[$fid] = array_merge($shares[$fid], $data);
997
+            }
998
+            return $shares;
999
+        }, []);
1000
+    }
1001
+
1002
+    /**
1003
+     * @inheritdoc
1004
+     */
1005
+    public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0) {
1006
+        if ($path !== null &&
1007
+                !($path instanceof \OCP\Files\File) &&
1008
+                !($path instanceof \OCP\Files\Folder)) {
1009
+            throw new \InvalidArgumentException('invalid path');
1010
+        }
1011
+
1012
+        try {
1013
+            $provider = $this->factory->getProviderForType($shareType);
1014
+        } catch (ProviderException $e) {
1015
+            return [];
1016
+        }
1017
+
1018
+        $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1019
+
1020
+        /*
1021 1021
 		 * Work around so we don't return expired shares but still follow
1022 1022
 		 * proper pagination.
1023 1023
 		 */
1024 1024
 
1025
-		$shares2 = [];
1026
-
1027
-		while(true) {
1028
-			$added = 0;
1029
-			foreach ($shares as $share) {
1030
-
1031
-				try {
1032
-					$this->checkExpireDate($share);
1033
-				} catch (ShareNotFound $e) {
1034
-					//Ignore since this basically means the share is deleted
1035
-					continue;
1036
-				}
1037
-
1038
-				$added++;
1039
-				$shares2[] = $share;
1040
-
1041
-				if (count($shares2) === $limit) {
1042
-					break;
1043
-				}
1044
-			}
1045
-
1046
-			if (count($shares2) === $limit) {
1047
-				break;
1048
-			}
1049
-
1050
-			// If there was no limit on the select we are done
1051
-			if ($limit === -1) {
1052
-				break;
1053
-			}
1054
-
1055
-			$offset += $added;
1056
-
1057
-			// Fetch again $limit shares
1058
-			$shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1059
-
1060
-			// No more shares means we are done
1061
-			if (empty($shares)) {
1062
-				break;
1063
-			}
1064
-		}
1065
-
1066
-		$shares = $shares2;
1067
-
1068
-		return $shares;
1069
-	}
1070
-
1071
-	/**
1072
-	 * @inheritdoc
1073
-	 */
1074
-	public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1075
-		try {
1076
-			$provider = $this->factory->getProviderForType($shareType);
1077
-		} catch (ProviderException $e) {
1078
-			return [];
1079
-		}
1080
-
1081
-		$shares = $provider->getSharedWith($userId, $shareType, $node, $limit, $offset);
1082
-
1083
-		// remove all shares which are already expired
1084
-		foreach ($shares as $key => $share) {
1085
-			try {
1086
-				$this->checkExpireDate($share);
1087
-			} catch (ShareNotFound $e) {
1088
-				unset($shares[$key]);
1089
-			}
1090
-		}
1091
-
1092
-		return $shares;
1093
-	}
1094
-
1095
-	/**
1096
-	 * @inheritdoc
1097
-	 */
1098
-	public function getShareById($id, $recipient = null) {
1099
-		if ($id === null) {
1100
-			throw new ShareNotFound();
1101
-		}
1102
-
1103
-		list($providerId, $id) = $this->splitFullId($id);
1104
-
1105
-		try {
1106
-			$provider = $this->factory->getProvider($providerId);
1107
-		} catch (ProviderException $e) {
1108
-			throw new ShareNotFound();
1109
-		}
1110
-
1111
-		$share = $provider->getShareById($id, $recipient);
1112
-
1113
-		$this->checkExpireDate($share);
1114
-
1115
-		return $share;
1116
-	}
1117
-
1118
-	/**
1119
-	 * Get all the shares for a given path
1120
-	 *
1121
-	 * @param \OCP\Files\Node $path
1122
-	 * @param int $page
1123
-	 * @param int $perPage
1124
-	 *
1125
-	 * @return Share[]
1126
-	 */
1127
-	public function getSharesByPath(\OCP\Files\Node $path, $page=0, $perPage=50) {
1128
-		return [];
1129
-	}
1130
-
1131
-	/**
1132
-	 * Get the share by token possible with password
1133
-	 *
1134
-	 * @param string $token
1135
-	 * @return Share
1136
-	 *
1137
-	 * @throws ShareNotFound
1138
-	 */
1139
-	public function getShareByToken($token) {
1140
-		$share = null;
1141
-		try {
1142
-			if($this->shareApiAllowLinks()) {
1143
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_LINK);
1144
-				$share = $provider->getShareByToken($token);
1145
-			}
1146
-		} catch (ProviderException $e) {
1147
-		} catch (ShareNotFound $e) {
1148
-		}
1149
-
1150
-
1151
-		// If it is not a link share try to fetch a federated share by token
1152
-		if ($share === null) {
1153
-			try {
1154
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE);
1155
-				$share = $provider->getShareByToken($token);
1156
-			} catch (ProviderException $e) {
1157
-			} catch (ShareNotFound $e) {
1158
-			}
1159
-		}
1160
-
1161
-		// If it is not a link share try to fetch a mail share by token
1162
-		if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
1163
-			try {
1164
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_EMAIL);
1165
-				$share = $provider->getShareByToken($token);
1166
-			} catch (ProviderException $e) {
1167
-			} catch (ShareNotFound $e) {
1168
-			}
1169
-		}
1170
-
1171
-		if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_CIRCLE)) {
1172
-			try {
1173
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_CIRCLE);
1174
-				$share = $provider->getShareByToken($token);
1175
-			} catch (ProviderException $e) {
1176
-			} catch (ShareNotFound $e) {
1177
-			}
1178
-		}
1179
-
1180
-		if ($share === null) {
1181
-			throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1182
-		}
1183
-
1184
-		$this->checkExpireDate($share);
1185
-
1186
-		/*
1025
+        $shares2 = [];
1026
+
1027
+        while(true) {
1028
+            $added = 0;
1029
+            foreach ($shares as $share) {
1030
+
1031
+                try {
1032
+                    $this->checkExpireDate($share);
1033
+                } catch (ShareNotFound $e) {
1034
+                    //Ignore since this basically means the share is deleted
1035
+                    continue;
1036
+                }
1037
+
1038
+                $added++;
1039
+                $shares2[] = $share;
1040
+
1041
+                if (count($shares2) === $limit) {
1042
+                    break;
1043
+                }
1044
+            }
1045
+
1046
+            if (count($shares2) === $limit) {
1047
+                break;
1048
+            }
1049
+
1050
+            // If there was no limit on the select we are done
1051
+            if ($limit === -1) {
1052
+                break;
1053
+            }
1054
+
1055
+            $offset += $added;
1056
+
1057
+            // Fetch again $limit shares
1058
+            $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1059
+
1060
+            // No more shares means we are done
1061
+            if (empty($shares)) {
1062
+                break;
1063
+            }
1064
+        }
1065
+
1066
+        $shares = $shares2;
1067
+
1068
+        return $shares;
1069
+    }
1070
+
1071
+    /**
1072
+     * @inheritdoc
1073
+     */
1074
+    public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1075
+        try {
1076
+            $provider = $this->factory->getProviderForType($shareType);
1077
+        } catch (ProviderException $e) {
1078
+            return [];
1079
+        }
1080
+
1081
+        $shares = $provider->getSharedWith($userId, $shareType, $node, $limit, $offset);
1082
+
1083
+        // remove all shares which are already expired
1084
+        foreach ($shares as $key => $share) {
1085
+            try {
1086
+                $this->checkExpireDate($share);
1087
+            } catch (ShareNotFound $e) {
1088
+                unset($shares[$key]);
1089
+            }
1090
+        }
1091
+
1092
+        return $shares;
1093
+    }
1094
+
1095
+    /**
1096
+     * @inheritdoc
1097
+     */
1098
+    public function getShareById($id, $recipient = null) {
1099
+        if ($id === null) {
1100
+            throw new ShareNotFound();
1101
+        }
1102
+
1103
+        list($providerId, $id) = $this->splitFullId($id);
1104
+
1105
+        try {
1106
+            $provider = $this->factory->getProvider($providerId);
1107
+        } catch (ProviderException $e) {
1108
+            throw new ShareNotFound();
1109
+        }
1110
+
1111
+        $share = $provider->getShareById($id, $recipient);
1112
+
1113
+        $this->checkExpireDate($share);
1114
+
1115
+        return $share;
1116
+    }
1117
+
1118
+    /**
1119
+     * Get all the shares for a given path
1120
+     *
1121
+     * @param \OCP\Files\Node $path
1122
+     * @param int $page
1123
+     * @param int $perPage
1124
+     *
1125
+     * @return Share[]
1126
+     */
1127
+    public function getSharesByPath(\OCP\Files\Node $path, $page=0, $perPage=50) {
1128
+        return [];
1129
+    }
1130
+
1131
+    /**
1132
+     * Get the share by token possible with password
1133
+     *
1134
+     * @param string $token
1135
+     * @return Share
1136
+     *
1137
+     * @throws ShareNotFound
1138
+     */
1139
+    public function getShareByToken($token) {
1140
+        $share = null;
1141
+        try {
1142
+            if($this->shareApiAllowLinks()) {
1143
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_LINK);
1144
+                $share = $provider->getShareByToken($token);
1145
+            }
1146
+        } catch (ProviderException $e) {
1147
+        } catch (ShareNotFound $e) {
1148
+        }
1149
+
1150
+
1151
+        // If it is not a link share try to fetch a federated share by token
1152
+        if ($share === null) {
1153
+            try {
1154
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE);
1155
+                $share = $provider->getShareByToken($token);
1156
+            } catch (ProviderException $e) {
1157
+            } catch (ShareNotFound $e) {
1158
+            }
1159
+        }
1160
+
1161
+        // If it is not a link share try to fetch a mail share by token
1162
+        if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
1163
+            try {
1164
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_EMAIL);
1165
+                $share = $provider->getShareByToken($token);
1166
+            } catch (ProviderException $e) {
1167
+            } catch (ShareNotFound $e) {
1168
+            }
1169
+        }
1170
+
1171
+        if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_CIRCLE)) {
1172
+            try {
1173
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_CIRCLE);
1174
+                $share = $provider->getShareByToken($token);
1175
+            } catch (ProviderException $e) {
1176
+            } catch (ShareNotFound $e) {
1177
+            }
1178
+        }
1179
+
1180
+        if ($share === null) {
1181
+            throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1182
+        }
1183
+
1184
+        $this->checkExpireDate($share);
1185
+
1186
+        /*
1187 1187
 		 * Reduce the permissions for link shares if public upload is not enabled
1188 1188
 		 */
1189
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
1190
-			!$this->shareApiLinkAllowPublicUpload()) {
1191
-			$share->setPermissions($share->getPermissions() & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE));
1192
-		}
1193
-
1194
-		return $share;
1195
-	}
1196
-
1197
-	protected function checkExpireDate($share) {
1198
-		if ($share->getExpirationDate() !== null &&
1199
-			$share->getExpirationDate() <= new \DateTime()) {
1200
-			$this->deleteShare($share);
1201
-			throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1202
-		}
1203
-
1204
-	}
1205
-
1206
-	/**
1207
-	 * Verify the password of a public share
1208
-	 *
1209
-	 * @param \OCP\Share\IShare $share
1210
-	 * @param string $password
1211
-	 * @return bool
1212
-	 */
1213
-	public function checkPassword(\OCP\Share\IShare $share, $password) {
1214
-		$passwordProtected = $share->getShareType() !== \OCP\Share::SHARE_TYPE_LINK
1215
-			|| $share->getShareType() !== \OCP\Share::SHARE_TYPE_EMAIL;
1216
-		if (!$passwordProtected) {
1217
-			//TODO maybe exception?
1218
-			return false;
1219
-		}
1220
-
1221
-		if ($password === null || $share->getPassword() === null) {
1222
-			return false;
1223
-		}
1224
-
1225
-		$newHash = '';
1226
-		if (!$this->hasher->verify($password, $share->getPassword(), $newHash)) {
1227
-			return false;
1228
-		}
1229
-
1230
-		if (!empty($newHash)) {
1231
-			$share->setPassword($newHash);
1232
-			$provider = $this->factory->getProviderForType($share->getShareType());
1233
-			$provider->update($share);
1234
-		}
1235
-
1236
-		return true;
1237
-	}
1238
-
1239
-	/**
1240
-	 * @inheritdoc
1241
-	 */
1242
-	public function userDeleted($uid) {
1243
-		$types = [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL];
1244
-
1245
-		foreach ($types as $type) {
1246
-			try {
1247
-				$provider = $this->factory->getProviderForType($type);
1248
-			} catch (ProviderException $e) {
1249
-				continue;
1250
-			}
1251
-			$provider->userDeleted($uid, $type);
1252
-		}
1253
-	}
1254
-
1255
-	/**
1256
-	 * @inheritdoc
1257
-	 */
1258
-	public function groupDeleted($gid) {
1259
-		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
1260
-		$provider->groupDeleted($gid);
1261
-	}
1262
-
1263
-	/**
1264
-	 * @inheritdoc
1265
-	 */
1266
-	public function userDeletedFromGroup($uid, $gid) {
1267
-		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
1268
-		$provider->userDeletedFromGroup($uid, $gid);
1269
-	}
1270
-
1271
-	/**
1272
-	 * Get access list to a path. This means
1273
-	 * all the users that can access a given path.
1274
-	 *
1275
-	 * Consider:
1276
-	 * -root
1277
-	 * |-folder1 (23)
1278
-	 *  |-folder2 (32)
1279
-	 *   |-fileA (42)
1280
-	 *
1281
-	 * fileA is shared with user1 and user1@server1
1282
-	 * folder2 is shared with group2 (user4 is a member of group2)
1283
-	 * folder1 is shared with user2 (renamed to "folder (1)") and user2@server2
1284
-	 *
1285
-	 * Then the access list to '/folder1/folder2/fileA' with $currentAccess is:
1286
-	 * [
1287
-	 *  users  => [
1288
-	 *      'user1' => ['node_id' => 42, 'node_path' => '/fileA'],
1289
-	 *      'user4' => ['node_id' => 32, 'node_path' => '/folder2'],
1290
-	 *      'user2' => ['node_id' => 23, 'node_path' => '/folder (1)'],
1291
-	 *  ],
1292
-	 *  remote => [
1293
-	 *      'user1@server1' => ['node_id' => 42, 'token' => 'SeCr3t'],
1294
-	 *      'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
1295
-	 *  ],
1296
-	 *  public => bool
1297
-	 *  mail => bool
1298
-	 * ]
1299
-	 *
1300
-	 * The access list to '/folder1/folder2/fileA' **without** $currentAccess is:
1301
-	 * [
1302
-	 *  users  => ['user1', 'user2', 'user4'],
1303
-	 *  remote => bool,
1304
-	 *  public => bool
1305
-	 *  mail => bool
1306
-	 * ]
1307
-	 *
1308
-	 * This is required for encryption/activity
1309
-	 *
1310
-	 * @param \OCP\Files\Node $path
1311
-	 * @param bool $recursive Should we check all parent folders as well
1312
-	 * @param bool $currentAccess Should the user have currently access to the file
1313
-	 * @return array
1314
-	 */
1315
-	public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false) {
1316
-		$owner = $path->getOwner()->getUID();
1317
-
1318
-		if ($currentAccess) {
1319
-			$al = ['users' => [], 'remote' => [], 'public' => false];
1320
-		} else {
1321
-			$al = ['users' => [], 'remote' => false, 'public' => false];
1322
-		}
1323
-		if (!$this->userManager->userExists($owner)) {
1324
-			return $al;
1325
-		}
1326
-
1327
-		//Get node for the owner
1328
-		$userFolder = $this->rootFolder->getUserFolder($owner);
1329
-		if ($path->getId() !== $userFolder->getId() && !$userFolder->isSubNode($path)) {
1330
-			$path = $userFolder->getById($path->getId())[0];
1331
-		}
1332
-
1333
-		$providers = $this->factory->getAllProviders();
1334
-
1335
-		/** @var Node[] $nodes */
1336
-		$nodes = [];
1337
-
1338
-
1339
-		if ($currentAccess) {
1340
-			$ownerPath = $path->getPath();
1341
-			$ownerPath = explode('/', $ownerPath, 4);
1342
-			if (count($ownerPath) < 4) {
1343
-				$ownerPath = '';
1344
-			} else {
1345
-				$ownerPath = $ownerPath[3];
1346
-			}
1347
-			$al['users'][$owner] = [
1348
-				'node_id' => $path->getId(),
1349
-				'node_path' => '/' . $ownerPath,
1350
-			];
1351
-		} else {
1352
-			$al['users'][] = $owner;
1353
-		}
1354
-
1355
-		// Collect all the shares
1356
-		while ($path->getPath() !== $userFolder->getPath()) {
1357
-			$nodes[] = $path;
1358
-			if (!$recursive) {
1359
-				break;
1360
-			}
1361
-			$path = $path->getParent();
1362
-		}
1363
-
1364
-		foreach ($providers as $provider) {
1365
-			$tmp = $provider->getAccessList($nodes, $currentAccess);
1366
-
1367
-			foreach ($tmp as $k => $v) {
1368
-				if (isset($al[$k])) {
1369
-					if (is_array($al[$k])) {
1370
-						$al[$k] = array_merge($al[$k], $v);
1371
-					} else {
1372
-						$al[$k] = $al[$k] || $v;
1373
-					}
1374
-				} else {
1375
-					$al[$k] = $v;
1376
-				}
1377
-			}
1378
-		}
1379
-
1380
-		return $al;
1381
-	}
1382
-
1383
-	/**
1384
-	 * Create a new share
1385
-	 * @return \OCP\Share\IShare;
1386
-	 */
1387
-	public function newShare() {
1388
-		return new \OC\Share20\Share($this->rootFolder, $this->userManager);
1389
-	}
1390
-
1391
-	/**
1392
-	 * Is the share API enabled
1393
-	 *
1394
-	 * @return bool
1395
-	 */
1396
-	public function shareApiEnabled() {
1397
-		return $this->config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes';
1398
-	}
1399
-
1400
-	/**
1401
-	 * Is public link sharing enabled
1402
-	 *
1403
-	 * @return bool
1404
-	 */
1405
-	public function shareApiAllowLinks() {
1406
-		return $this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes';
1407
-	}
1408
-
1409
-	/**
1410
-	 * Is password on public link requires
1411
-	 *
1412
-	 * @return bool
1413
-	 */
1414
-	public function shareApiLinkEnforcePassword() {
1415
-		return $this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes';
1416
-	}
1417
-
1418
-	/**
1419
-	 * Is default expire date enabled
1420
-	 *
1421
-	 * @return bool
1422
-	 */
1423
-	public function shareApiLinkDefaultExpireDate() {
1424
-		return $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
1425
-	}
1426
-
1427
-	/**
1428
-	 * Is default expire date enforced
1429
-	 *`
1430
-	 * @return bool
1431
-	 */
1432
-	public function shareApiLinkDefaultExpireDateEnforced() {
1433
-		return $this->shareApiLinkDefaultExpireDate() &&
1434
-			$this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
1435
-	}
1436
-
1437
-	/**
1438
-	 * Number of default expire days
1439
-	 *shareApiLinkAllowPublicUpload
1440
-	 * @return int
1441
-	 */
1442
-	public function shareApiLinkDefaultExpireDays() {
1443
-		return (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1444
-	}
1445
-
1446
-	/**
1447
-	 * Allow public upload on link shares
1448
-	 *
1449
-	 * @return bool
1450
-	 */
1451
-	public function shareApiLinkAllowPublicUpload() {
1452
-		return $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes';
1453
-	}
1454
-
1455
-	/**
1456
-	 * check if user can only share with group members
1457
-	 * @return bool
1458
-	 */
1459
-	public function shareWithGroupMembersOnly() {
1460
-		return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
1461
-	}
1462
-
1463
-	/**
1464
-	 * Check if users can share with groups
1465
-	 * @return bool
1466
-	 */
1467
-	public function allowGroupSharing() {
1468
-		return $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes';
1469
-	}
1470
-
1471
-	/**
1472
-	 * Copied from \OC_Util::isSharingDisabledForUser
1473
-	 *
1474
-	 * TODO: Deprecate fuction from OC_Util
1475
-	 *
1476
-	 * @param string $userId
1477
-	 * @return bool
1478
-	 */
1479
-	public function sharingDisabledForUser($userId) {
1480
-		if ($userId === null) {
1481
-			return false;
1482
-		}
1483
-
1484
-		if (isset($this->sharingDisabledForUsersCache[$userId])) {
1485
-			return $this->sharingDisabledForUsersCache[$userId];
1486
-		}
1487
-
1488
-		if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
1489
-			$groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
1490
-			$excludedGroups = json_decode($groupsList);
1491
-			if (is_null($excludedGroups)) {
1492
-				$excludedGroups = explode(',', $groupsList);
1493
-				$newValue = json_encode($excludedGroups);
1494
-				$this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
1495
-			}
1496
-			$user = $this->userManager->get($userId);
1497
-			$usersGroups = $this->groupManager->getUserGroupIds($user);
1498
-			if (!empty($usersGroups)) {
1499
-				$remainingGroups = array_diff($usersGroups, $excludedGroups);
1500
-				// if the user is only in groups which are disabled for sharing then
1501
-				// sharing is also disabled for the user
1502
-				if (empty($remainingGroups)) {
1503
-					$this->sharingDisabledForUsersCache[$userId] = true;
1504
-					return true;
1505
-				}
1506
-			}
1507
-		}
1508
-
1509
-		$this->sharingDisabledForUsersCache[$userId] = false;
1510
-		return false;
1511
-	}
1512
-
1513
-	/**
1514
-	 * @inheritdoc
1515
-	 */
1516
-	public function outgoingServer2ServerSharesAllowed() {
1517
-		return $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
1518
-	}
1519
-
1520
-	/**
1521
-	 * @inheritdoc
1522
-	 */
1523
-	public function shareProviderExists($shareType) {
1524
-		try {
1525
-			$this->factory->getProviderForType($shareType);
1526
-		} catch (ProviderException $e) {
1527
-			return false;
1528
-		}
1529
-
1530
-		return true;
1531
-	}
1189
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
1190
+            !$this->shareApiLinkAllowPublicUpload()) {
1191
+            $share->setPermissions($share->getPermissions() & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE));
1192
+        }
1193
+
1194
+        return $share;
1195
+    }
1196
+
1197
+    protected function checkExpireDate($share) {
1198
+        if ($share->getExpirationDate() !== null &&
1199
+            $share->getExpirationDate() <= new \DateTime()) {
1200
+            $this->deleteShare($share);
1201
+            throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1202
+        }
1203
+
1204
+    }
1205
+
1206
+    /**
1207
+     * Verify the password of a public share
1208
+     *
1209
+     * @param \OCP\Share\IShare $share
1210
+     * @param string $password
1211
+     * @return bool
1212
+     */
1213
+    public function checkPassword(\OCP\Share\IShare $share, $password) {
1214
+        $passwordProtected = $share->getShareType() !== \OCP\Share::SHARE_TYPE_LINK
1215
+            || $share->getShareType() !== \OCP\Share::SHARE_TYPE_EMAIL;
1216
+        if (!$passwordProtected) {
1217
+            //TODO maybe exception?
1218
+            return false;
1219
+        }
1220
+
1221
+        if ($password === null || $share->getPassword() === null) {
1222
+            return false;
1223
+        }
1224
+
1225
+        $newHash = '';
1226
+        if (!$this->hasher->verify($password, $share->getPassword(), $newHash)) {
1227
+            return false;
1228
+        }
1229
+
1230
+        if (!empty($newHash)) {
1231
+            $share->setPassword($newHash);
1232
+            $provider = $this->factory->getProviderForType($share->getShareType());
1233
+            $provider->update($share);
1234
+        }
1235
+
1236
+        return true;
1237
+    }
1238
+
1239
+    /**
1240
+     * @inheritdoc
1241
+     */
1242
+    public function userDeleted($uid) {
1243
+        $types = [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL];
1244
+
1245
+        foreach ($types as $type) {
1246
+            try {
1247
+                $provider = $this->factory->getProviderForType($type);
1248
+            } catch (ProviderException $e) {
1249
+                continue;
1250
+            }
1251
+            $provider->userDeleted($uid, $type);
1252
+        }
1253
+    }
1254
+
1255
+    /**
1256
+     * @inheritdoc
1257
+     */
1258
+    public function groupDeleted($gid) {
1259
+        $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
1260
+        $provider->groupDeleted($gid);
1261
+    }
1262
+
1263
+    /**
1264
+     * @inheritdoc
1265
+     */
1266
+    public function userDeletedFromGroup($uid, $gid) {
1267
+        $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
1268
+        $provider->userDeletedFromGroup($uid, $gid);
1269
+    }
1270
+
1271
+    /**
1272
+     * Get access list to a path. This means
1273
+     * all the users that can access a given path.
1274
+     *
1275
+     * Consider:
1276
+     * -root
1277
+     * |-folder1 (23)
1278
+     *  |-folder2 (32)
1279
+     *   |-fileA (42)
1280
+     *
1281
+     * fileA is shared with user1 and user1@server1
1282
+     * folder2 is shared with group2 (user4 is a member of group2)
1283
+     * folder1 is shared with user2 (renamed to "folder (1)") and user2@server2
1284
+     *
1285
+     * Then the access list to '/folder1/folder2/fileA' with $currentAccess is:
1286
+     * [
1287
+     *  users  => [
1288
+     *      'user1' => ['node_id' => 42, 'node_path' => '/fileA'],
1289
+     *      'user4' => ['node_id' => 32, 'node_path' => '/folder2'],
1290
+     *      'user2' => ['node_id' => 23, 'node_path' => '/folder (1)'],
1291
+     *  ],
1292
+     *  remote => [
1293
+     *      'user1@server1' => ['node_id' => 42, 'token' => 'SeCr3t'],
1294
+     *      'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
1295
+     *  ],
1296
+     *  public => bool
1297
+     *  mail => bool
1298
+     * ]
1299
+     *
1300
+     * The access list to '/folder1/folder2/fileA' **without** $currentAccess is:
1301
+     * [
1302
+     *  users  => ['user1', 'user2', 'user4'],
1303
+     *  remote => bool,
1304
+     *  public => bool
1305
+     *  mail => bool
1306
+     * ]
1307
+     *
1308
+     * This is required for encryption/activity
1309
+     *
1310
+     * @param \OCP\Files\Node $path
1311
+     * @param bool $recursive Should we check all parent folders as well
1312
+     * @param bool $currentAccess Should the user have currently access to the file
1313
+     * @return array
1314
+     */
1315
+    public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false) {
1316
+        $owner = $path->getOwner()->getUID();
1317
+
1318
+        if ($currentAccess) {
1319
+            $al = ['users' => [], 'remote' => [], 'public' => false];
1320
+        } else {
1321
+            $al = ['users' => [], 'remote' => false, 'public' => false];
1322
+        }
1323
+        if (!$this->userManager->userExists($owner)) {
1324
+            return $al;
1325
+        }
1326
+
1327
+        //Get node for the owner
1328
+        $userFolder = $this->rootFolder->getUserFolder($owner);
1329
+        if ($path->getId() !== $userFolder->getId() && !$userFolder->isSubNode($path)) {
1330
+            $path = $userFolder->getById($path->getId())[0];
1331
+        }
1332
+
1333
+        $providers = $this->factory->getAllProviders();
1334
+
1335
+        /** @var Node[] $nodes */
1336
+        $nodes = [];
1337
+
1338
+
1339
+        if ($currentAccess) {
1340
+            $ownerPath = $path->getPath();
1341
+            $ownerPath = explode('/', $ownerPath, 4);
1342
+            if (count($ownerPath) < 4) {
1343
+                $ownerPath = '';
1344
+            } else {
1345
+                $ownerPath = $ownerPath[3];
1346
+            }
1347
+            $al['users'][$owner] = [
1348
+                'node_id' => $path->getId(),
1349
+                'node_path' => '/' . $ownerPath,
1350
+            ];
1351
+        } else {
1352
+            $al['users'][] = $owner;
1353
+        }
1354
+
1355
+        // Collect all the shares
1356
+        while ($path->getPath() !== $userFolder->getPath()) {
1357
+            $nodes[] = $path;
1358
+            if (!$recursive) {
1359
+                break;
1360
+            }
1361
+            $path = $path->getParent();
1362
+        }
1363
+
1364
+        foreach ($providers as $provider) {
1365
+            $tmp = $provider->getAccessList($nodes, $currentAccess);
1366
+
1367
+            foreach ($tmp as $k => $v) {
1368
+                if (isset($al[$k])) {
1369
+                    if (is_array($al[$k])) {
1370
+                        $al[$k] = array_merge($al[$k], $v);
1371
+                    } else {
1372
+                        $al[$k] = $al[$k] || $v;
1373
+                    }
1374
+                } else {
1375
+                    $al[$k] = $v;
1376
+                }
1377
+            }
1378
+        }
1379
+
1380
+        return $al;
1381
+    }
1382
+
1383
+    /**
1384
+     * Create a new share
1385
+     * @return \OCP\Share\IShare;
1386
+     */
1387
+    public function newShare() {
1388
+        return new \OC\Share20\Share($this->rootFolder, $this->userManager);
1389
+    }
1390
+
1391
+    /**
1392
+     * Is the share API enabled
1393
+     *
1394
+     * @return bool
1395
+     */
1396
+    public function shareApiEnabled() {
1397
+        return $this->config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes';
1398
+    }
1399
+
1400
+    /**
1401
+     * Is public link sharing enabled
1402
+     *
1403
+     * @return bool
1404
+     */
1405
+    public function shareApiAllowLinks() {
1406
+        return $this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes';
1407
+    }
1408
+
1409
+    /**
1410
+     * Is password on public link requires
1411
+     *
1412
+     * @return bool
1413
+     */
1414
+    public function shareApiLinkEnforcePassword() {
1415
+        return $this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes';
1416
+    }
1417
+
1418
+    /**
1419
+     * Is default expire date enabled
1420
+     *
1421
+     * @return bool
1422
+     */
1423
+    public function shareApiLinkDefaultExpireDate() {
1424
+        return $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
1425
+    }
1426
+
1427
+    /**
1428
+     * Is default expire date enforced
1429
+     *`
1430
+     * @return bool
1431
+     */
1432
+    public function shareApiLinkDefaultExpireDateEnforced() {
1433
+        return $this->shareApiLinkDefaultExpireDate() &&
1434
+            $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
1435
+    }
1436
+
1437
+    /**
1438
+     * Number of default expire days
1439
+     *shareApiLinkAllowPublicUpload
1440
+     * @return int
1441
+     */
1442
+    public function shareApiLinkDefaultExpireDays() {
1443
+        return (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1444
+    }
1445
+
1446
+    /**
1447
+     * Allow public upload on link shares
1448
+     *
1449
+     * @return bool
1450
+     */
1451
+    public function shareApiLinkAllowPublicUpload() {
1452
+        return $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes';
1453
+    }
1454
+
1455
+    /**
1456
+     * check if user can only share with group members
1457
+     * @return bool
1458
+     */
1459
+    public function shareWithGroupMembersOnly() {
1460
+        return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
1461
+    }
1462
+
1463
+    /**
1464
+     * Check if users can share with groups
1465
+     * @return bool
1466
+     */
1467
+    public function allowGroupSharing() {
1468
+        return $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes';
1469
+    }
1470
+
1471
+    /**
1472
+     * Copied from \OC_Util::isSharingDisabledForUser
1473
+     *
1474
+     * TODO: Deprecate fuction from OC_Util
1475
+     *
1476
+     * @param string $userId
1477
+     * @return bool
1478
+     */
1479
+    public function sharingDisabledForUser($userId) {
1480
+        if ($userId === null) {
1481
+            return false;
1482
+        }
1483
+
1484
+        if (isset($this->sharingDisabledForUsersCache[$userId])) {
1485
+            return $this->sharingDisabledForUsersCache[$userId];
1486
+        }
1487
+
1488
+        if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
1489
+            $groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
1490
+            $excludedGroups = json_decode($groupsList);
1491
+            if (is_null($excludedGroups)) {
1492
+                $excludedGroups = explode(',', $groupsList);
1493
+                $newValue = json_encode($excludedGroups);
1494
+                $this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
1495
+            }
1496
+            $user = $this->userManager->get($userId);
1497
+            $usersGroups = $this->groupManager->getUserGroupIds($user);
1498
+            if (!empty($usersGroups)) {
1499
+                $remainingGroups = array_diff($usersGroups, $excludedGroups);
1500
+                // if the user is only in groups which are disabled for sharing then
1501
+                // sharing is also disabled for the user
1502
+                if (empty($remainingGroups)) {
1503
+                    $this->sharingDisabledForUsersCache[$userId] = true;
1504
+                    return true;
1505
+                }
1506
+            }
1507
+        }
1508
+
1509
+        $this->sharingDisabledForUsersCache[$userId] = false;
1510
+        return false;
1511
+    }
1512
+
1513
+    /**
1514
+     * @inheritdoc
1515
+     */
1516
+    public function outgoingServer2ServerSharesAllowed() {
1517
+        return $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
1518
+    }
1519
+
1520
+    /**
1521
+     * @inheritdoc
1522
+     */
1523
+    public function shareProviderExists($shareType) {
1524
+        try {
1525
+            $this->factory->getProviderForType($shareType);
1526
+        } catch (ProviderException $e) {
1527
+            return false;
1528
+        }
1529
+
1530
+        return true;
1531
+    }
1532 1532
 
1533 1533
 }
Please login to merge, or discard this patch.
Spacing   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -340,7 +340,7 @@  discard block
 block discarded – undo
340 340
 
341 341
 		if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
342 342
 			$expirationDate = new \DateTime();
343
-			$expirationDate->setTime(0,0,0);
343
+			$expirationDate->setTime(0, 0, 0);
344 344
 			$expirationDate->add(new \DateInterval('P'.$this->shareApiLinkDefaultExpireDays().'D'));
345 345
 		}
346 346
 
@@ -352,7 +352,7 @@  discard block
 block discarded – undo
352 352
 
353 353
 			$date = new \DateTime();
354 354
 			$date->setTime(0, 0, 0);
355
-			$date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
355
+			$date->add(new \DateInterval('P'.$this->shareApiLinkDefaultExpireDays().'D'));
356 356
 			if ($date < $expirationDate) {
357 357
 				$message = $this->l->t('Can’t set expiration date more than %s days in the future', [$this->shareApiLinkDefaultExpireDays()]);
358 358
 				throw new GenericShareException($message, $message, 404);
@@ -405,7 +405,7 @@  discard block
 block discarded – undo
405 405
 		 */
406 406
 		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_USER);
407 407
 		$existingShares = $provider->getSharesByPath($share->getNode());
408
-		foreach($existingShares as $existingShare) {
408
+		foreach ($existingShares as $existingShare) {
409 409
 			// Ignore if it is the same share
410 410
 			try {
411 411
 				if ($existingShare->getFullId() === $share->getFullId()) {
@@ -462,7 +462,7 @@  discard block
 block discarded – undo
462 462
 		 */
463 463
 		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
464 464
 		$existingShares = $provider->getSharesByPath($share->getNode());
465
-		foreach($existingShares as $existingShare) {
465
+		foreach ($existingShares as $existingShare) {
466 466
 			try {
467 467
 				if ($existingShare->getFullId() === $share->getFullId()) {
468 468
 					continue;
@@ -531,7 +531,7 @@  discard block
 block discarded – undo
531 531
 		// Make sure that we do not share a path that contains a shared mountpoint
532 532
 		if ($path instanceof \OCP\Files\Folder) {
533 533
 			$mounts = $this->mountManager->findIn($path->getPath());
534
-			foreach($mounts as $mount) {
534
+			foreach ($mounts as $mount) {
535 535
 				if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
536 536
 					throw new \InvalidArgumentException('Path contains files shared with you');
537 537
 				}
@@ -579,7 +579,7 @@  discard block
 block discarded – undo
579 579
 		$storage = $share->getNode()->getStorage();
580 580
 		if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
581 581
 			$parent = $share->getNode()->getParent();
582
-			while($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
582
+			while ($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
583 583
 				$parent = $parent->getParent();
584 584
 			}
585 585
 			$share->setShareOwner($parent->getOwner()->getUID());
@@ -632,7 +632,7 @@  discard block
 block discarded – undo
632 632
 		}
633 633
 
634 634
 		// Generate the target
635
-		$target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getNode()->getName();
635
+		$target = $this->config->getSystemValue('share_folder', '/').'/'.$share->getNode()->getName();
636 636
 		$target = \OC\Files\Filesystem::normalizePath($target);
637 637
 		$share->setTarget($target);
638 638
 
@@ -660,17 +660,17 @@  discard block
 block discarded – undo
660 660
 				if ($emailAddress !== null && $emailAddress !== '') {
661 661
 					$this->sendMailNotification(
662 662
 						$share->getNode()->getName(),
663
-						$this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', [ 'fileid' => $share->getNode()->getId() ]),
663
+						$this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]),
664 664
 						$share->getSharedBy(),
665 665
 						$emailAddress,
666 666
 						$share->getExpirationDate()
667 667
 					);
668
-					$this->logger->debug('Send share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']);
668
+					$this->logger->debug('Send share notification to '.$emailAddress.' for share with ID '.$share->getId(), ['app' => 'share']);
669 669
 				} else {
670
-					$this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']);
670
+					$this->logger->debug('Share notification not send to '.$share->getSharedWith().' because email address is not set.', ['app' => 'share']);
671 671
 				}
672 672
 			} else {
673
-				$this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']);
673
+				$this->logger->debug('Share notification not send to '.$share->getSharedWith().' because user could not be found.', ['app' => 'share']);
674 674
 			}
675 675
 		}
676 676
 
@@ -692,7 +692,7 @@  discard block
 block discarded – undo
692 692
 											\DateTime $expiration = null) {
693 693
 		$initiatorUser = $this->userManager->get($initiator);
694 694
 		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
695
-		$subject = (string)$this->l->t('%s shared »%s« with you', array($initiatorDisplayName, $filename));
695
+		$subject = (string) $this->l->t('%s shared »%s« with you', array($initiatorDisplayName, $filename));
696 696
 
697 697
 		$message = $this->mailer->createMessage();
698 698
 
@@ -709,7 +709,7 @@  discard block
 block discarded – undo
709 709
 		$text = $this->l->t('%s shared »%s« with you.', [$initiatorDisplayName, $filename]);
710 710
 
711 711
 		$emailTemplate->addBodyText(
712
-			$text . ' ' . $this->l->t('Click the button below to open it.'),
712
+			$text.' '.$this->l->t('Click the button below to open it.'),
713 713
 			$text
714 714
 		);
715 715
 		$emailTemplate->addBodyButton(
@@ -733,9 +733,9 @@  discard block
 block discarded – undo
733 733
 		// The "Reply-To" is set to the sharer if an mail address is configured
734 734
 		// also the default footer contains a "Do not reply" which needs to be adjusted.
735 735
 		$initiatorEmail = $initiatorUser->getEMailAddress();
736
-		if($initiatorEmail !== null) {
736
+		if ($initiatorEmail !== null) {
737 737
 			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
738
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
738
+			$emailTemplate->addFooter($instanceName.' - '.$this->defaults->getSlogan());
739 739
 		} else {
740 740
 			$emailTemplate->addFooter();
741 741
 		}
@@ -946,7 +946,7 @@  discard block
 block discarded – undo
946 946
 	 * @param string $recipientId
947 947
 	 */
948 948
 	public function deleteFromSelf(\OCP\Share\IShare $share, $recipientId) {
949
-		list($providerId, ) = $this->splitFullId($share->getFullId());
949
+		list($providerId,) = $this->splitFullId($share->getFullId());
950 950
 		$provider = $this->factory->getProvider($providerId);
951 951
 
952 952
 		$provider->deleteFromSelf($share, $recipientId);
@@ -969,7 +969,7 @@  discard block
 block discarded – undo
969 969
 		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
970 970
 			$sharedWith = $this->groupManager->get($share->getSharedWith());
971 971
 			if (is_null($sharedWith)) {
972
-				throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist');
972
+				throw new \InvalidArgumentException('Group "'.$share->getSharedWith().'" does not exist');
973 973
 			}
974 974
 			$recipient = $this->userManager->get($recipientId);
975 975
 			if (!$sharedWith->inGroup($recipient)) {
@@ -977,7 +977,7 @@  discard block
 block discarded – undo
977 977
 			}
978 978
 		}
979 979
 
980
-		list($providerId, ) = $this->splitFullId($share->getFullId());
980
+		list($providerId,) = $this->splitFullId($share->getFullId());
981 981
 		$provider = $this->factory->getProvider($providerId);
982 982
 
983 983
 		$provider->move($share, $recipientId);
@@ -1024,7 +1024,7 @@  discard block
 block discarded – undo
1024 1024
 
1025 1025
 		$shares2 = [];
1026 1026
 
1027
-		while(true) {
1027
+		while (true) {
1028 1028
 			$added = 0;
1029 1029
 			foreach ($shares as $share) {
1030 1030
 
@@ -1124,7 +1124,7 @@  discard block
 block discarded – undo
1124 1124
 	 *
1125 1125
 	 * @return Share[]
1126 1126
 	 */
1127
-	public function getSharesByPath(\OCP\Files\Node $path, $page=0, $perPage=50) {
1127
+	public function getSharesByPath(\OCP\Files\Node $path, $page = 0, $perPage = 50) {
1128 1128
 		return [];
1129 1129
 	}
1130 1130
 
@@ -1139,7 +1139,7 @@  discard block
 block discarded – undo
1139 1139
 	public function getShareByToken($token) {
1140 1140
 		$share = null;
1141 1141
 		try {
1142
-			if($this->shareApiAllowLinks()) {
1142
+			if ($this->shareApiAllowLinks()) {
1143 1143
 				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_LINK);
1144 1144
 				$share = $provider->getShareByToken($token);
1145 1145
 			}
@@ -1346,7 +1346,7 @@  discard block
 block discarded – undo
1346 1346
 			}
1347 1347
 			$al['users'][$owner] = [
1348 1348
 				'node_id' => $path->getId(),
1349
-				'node_path' => '/' . $ownerPath,
1349
+				'node_path' => '/'.$ownerPath,
1350 1350
 			];
1351 1351
 		} else {
1352 1352
 			$al['users'][] = $owner;
@@ -1440,7 +1440,7 @@  discard block
 block discarded – undo
1440 1440
 	 * @return int
1441 1441
 	 */
1442 1442
 	public function shareApiLinkDefaultExpireDays() {
1443
-		return (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1443
+		return (int) $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1444 1444
 	}
1445 1445
 
1446 1446
 	/**
Please login to merge, or discard this patch.