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