Completed
Push — master ( 031add...ab3599 )
by Morris
40:08 queued 20:01
created
apps/dav/lib/CalDAV/Schedule/IMipPlugin.php 2 patches
Indentation   +489 added lines, -489 removed lines patch added patch discarded remove patch
@@ -60,494 +60,494 @@
 block discarded – undo
60 60
  */
61 61
 class IMipPlugin extends SabreIMipPlugin {
62 62
 
63
-	/** @var string */
64
-	private $userId;
65
-
66
-	/** @var IConfig */
67
-	private $config;
68
-
69
-	/** @var IMailer */
70
-	private $mailer;
71
-
72
-	/** @var ILogger */
73
-	private $logger;
74
-
75
-	/** @var ITimeFactory */
76
-	private $timeFactory;
77
-
78
-	/** @var L10NFactory */
79
-	private $l10nFactory;
80
-
81
-	/** @var IURLGenerator */
82
-	private $urlGenerator;
83
-
84
-	/** @var ISecureRandom */
85
-	private $random;
86
-
87
-	/** @var IDBConnection */
88
-	private $db;
89
-
90
-	/** @var Defaults */
91
-	private $defaults;
92
-
93
-	const MAX_DATE = '2038-01-01';
94
-
95
-	const METHOD_REQUEST = 'request';
96
-	const METHOD_REPLY = 'reply';
97
-	const METHOD_CANCEL = 'cancel';
98
-
99
-	/**
100
-	 * @param IConfig $config
101
-	 * @param IMailer $mailer
102
-	 * @param ILogger $logger
103
-	 * @param ITimeFactory $timeFactory
104
-	 * @param L10NFactory $l10nFactory
105
-	 * @param IUrlGenerator $urlGenerator
106
-	 * @param Defaults $defaults
107
-	 * @param ISecureRandom $random
108
-	 * @param IDBConnection $db
109
-	 * @param string $userId
110
-	 */
111
-	public function __construct(IConfig $config, IMailer $mailer, ILogger $logger,
112
-								ITimeFactory $timeFactory, L10NFactory $l10nFactory,
113
-								IURLGenerator $urlGenerator, Defaults $defaults,
114
-								ISecureRandom $random, IDBConnection $db, $userId) {
115
-		parent::__construct('');
116
-		$this->userId = $userId;
117
-		$this->config = $config;
118
-		$this->mailer = $mailer;
119
-		$this->logger = $logger;
120
-		$this->timeFactory = $timeFactory;
121
-		$this->l10nFactory = $l10nFactory;
122
-		$this->urlGenerator = $urlGenerator;
123
-		$this->random = $random;
124
-		$this->db = $db;
125
-		$this->defaults = $defaults;
126
-	}
127
-
128
-	/**
129
-	 * Event handler for the 'schedule' event.
130
-	 *
131
-	 * @param Message $iTipMessage
132
-	 * @return void
133
-	 */
134
-	public function schedule(Message $iTipMessage) {
135
-
136
-		// Not sending any emails if the system considers the update
137
-		// insignificant.
138
-		if (!$iTipMessage->significantChange) {
139
-			if (!$iTipMessage->scheduleStatus) {
140
-				$iTipMessage->scheduleStatus = '1.0;We got the message, but it\'s not significant enough to warrant an email';
141
-			}
142
-			return;
143
-		}
144
-
145
-		$summary = $iTipMessage->message->VEVENT->SUMMARY;
146
-
147
-		if (parse_url($iTipMessage->sender, PHP_URL_SCHEME) !== 'mailto') {
148
-			return;
149
-		}
150
-
151
-		if (parse_url($iTipMessage->recipient, PHP_URL_SCHEME) !== 'mailto') {
152
-			return;
153
-		}
154
-
155
-		// don't send out mails for events that already took place
156
-		$lastOccurrence = $this->getLastOccurrence($iTipMessage->message);
157
-		$currentTime = $this->timeFactory->getTime();
158
-		if ($lastOccurrence < $currentTime) {
159
-			return;
160
-		}
161
-
162
-		// Strip off mailto:
163
-		$sender = substr($iTipMessage->sender, 7);
164
-		$recipient = substr($iTipMessage->recipient, 7);
165
-
166
-		$senderName = $iTipMessage->senderName ?: null;
167
-		$recipientName = $iTipMessage->recipientName ?: null;
168
-
169
-		/** @var VEvent $vevent */
170
-		$vevent = $iTipMessage->message->VEVENT;
171
-
172
-		$attendee = $this->getCurrentAttendee($iTipMessage);
173
-		$defaultLang = $this->config->getUserValue($this->userId, 'core', 'lang', $this->l10nFactory->findLanguage());
174
-		$lang = $this->getAttendeeLangOrDefault($defaultLang, $attendee);
175
-		$l10n = $this->l10nFactory->get('dav', $lang);
176
-
177
-		$meetingAttendeeName = $recipientName ?: $recipient;
178
-		$meetingInviteeName = $senderName ?: $sender;
179
-
180
-		$meetingTitle = $vevent->SUMMARY;
181
-		$meetingDescription = $vevent->DESCRIPTION;
182
-
183
-		$start = $vevent->DTSTART;
184
-		if (isset($vevent->DTEND)) {
185
-			$end = $vevent->DTEND;
186
-		} elseif (isset($vevent->DURATION)) {
187
-			$isFloating = $vevent->DTSTART->isFloating();
188
-			$end = clone $vevent->DTSTART;
189
-			$endDateTime = $end->getDateTime();
190
-			$endDateTime = $endDateTime->add(DateTimeParser::parse($vevent->DURATION->getValue()));
191
-			$end->setDateTime($endDateTime, $isFloating);
192
-		} elseif (!$vevent->DTSTART->hasTime()) {
193
-			$isFloating = $vevent->DTSTART->isFloating();
194
-			$end = clone $vevent->DTSTART;
195
-			$endDateTime = $end->getDateTime();
196
-			$endDateTime = $endDateTime->modify('+1 day');
197
-			$end->setDateTime($endDateTime, $isFloating);
198
-		} else {
199
-			$end = clone $vevent->DTSTART;
200
-		}
201
-
202
-		$meetingWhen = $this->generateWhenString($l10n, $start, $end);
203
-
204
-		$meetingUrl = $vevent->URL;
205
-		$meetingLocation = $vevent->LOCATION;
206
-
207
-		$defaultVal = '--';
208
-
209
-		$method = self::METHOD_REQUEST;
210
-		switch (strtolower($iTipMessage->method)) {
211
-			case self::METHOD_REPLY:
212
-				$method = self::METHOD_REPLY;
213
-				break;
214
-			case self::METHOD_CANCEL:
215
-				$method = self::METHOD_CANCEL;
216
-				break;
217
-		}
218
-
219
-		$data = array(
220
-			'attendee_name' => (string)$meetingAttendeeName ?: $defaultVal,
221
-			'invitee_name' => (string)$meetingInviteeName ?: $defaultVal,
222
-			'meeting_title' => (string)$meetingTitle ?: $defaultVal,
223
-			'meeting_description' => (string)$meetingDescription ?: $defaultVal,
224
-			'meeting_url' => (string)$meetingUrl ?: $defaultVal,
225
-		);
226
-
227
-		$fromEMail = \OCP\Util::getDefaultEmailAddress('invitations-noreply');
228
-		$fromName = $l10n->t('%1$s via %2$s', [$senderName, $this->defaults->getName()]);
229
-
230
-		$message = $this->mailer->createMessage()
231
-			->setFrom([$fromEMail => $fromName])
232
-			->setReplyTo([$sender => $senderName])
233
-			->setTo([$recipient => $recipientName]);
234
-
235
-		$template = $this->mailer->createEMailTemplate('dav.calendarInvite.' . $method, $data);
236
-		$template->addHeader();
237
-
238
-		$this->addSubjectAndHeading($template, $l10n, $method, $summary,
239
-			$meetingAttendeeName, $meetingInviteeName);
240
-		$this->addBulletList($template, $l10n, $meetingWhen, $meetingLocation,
241
-			$meetingDescription, $meetingUrl);
242
-		$this->addResponseButtons($template, $l10n, $iTipMessage, $lastOccurrence);
243
-
244
-		$template->addFooter();
245
-		$message->useTemplate($template);
246
-
247
-		$attachment = $this->mailer->createAttachment(
248
-			$iTipMessage->message->serialize(),
249
-			'event.ics',// TODO(leon): Make file name unique, e.g. add event id
250
-			'text/calendar; method=' . $iTipMessage->method
251
-		);
252
-		$message->attach($attachment);
253
-
254
-		try {
255
-			$failed = $this->mailer->send($message);
256
-			$iTipMessage->scheduleStatus = '1.1; Scheduling message is sent via iMip';
257
-			if ($failed) {
258
-				$this->logger->error('Unable to deliver message to {failed}', ['app' => 'dav', 'failed' =>  implode(', ', $failed)]);
259
-				$iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
260
-			}
261
-		} catch(\Exception $ex) {
262
-			$this->logger->logException($ex, ['app' => 'dav']);
263
-			$iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
264
-		}
265
-	}
266
-
267
-	/**
268
-	 * check if event took place in the past already
269
-	 * @param VCalendar $vObject
270
-	 * @return int
271
-	 */
272
-	private function getLastOccurrence(VCalendar $vObject) {
273
-		/** @var VEvent $component */
274
-		$component = $vObject->VEVENT;
275
-
276
-		$firstOccurrence = $component->DTSTART->getDateTime()->getTimeStamp();
277
-		// Finding the last occurrence is a bit harder
278
-		if (!isset($component->RRULE)) {
279
-			if (isset($component->DTEND)) {
280
-				$lastOccurrence = $component->DTEND->getDateTime()->getTimeStamp();
281
-			} elseif (isset($component->DURATION)) {
282
-				/** @var \DateTime $endDate */
283
-				$endDate = clone $component->DTSTART->getDateTime();
284
-				// $component->DTEND->getDateTime() returns DateTimeImmutable
285
-				$endDate = $endDate->add(DateTimeParser::parse($component->DURATION->getValue()));
286
-				$lastOccurrence = $endDate->getTimestamp();
287
-			} elseif (!$component->DTSTART->hasTime()) {
288
-				/** @var \DateTime $endDate */
289
-				$endDate = clone $component->DTSTART->getDateTime();
290
-				// $component->DTSTART->getDateTime() returns DateTimeImmutable
291
-				$endDate = $endDate->modify('+1 day');
292
-				$lastOccurrence = $endDate->getTimestamp();
293
-			} else {
294
-				$lastOccurrence = $firstOccurrence;
295
-			}
296
-		} else {
297
-			$it = new EventIterator($vObject, (string)$component->UID);
298
-			$maxDate = new \DateTime(self::MAX_DATE);
299
-			if ($it->isInfinite()) {
300
-				$lastOccurrence = $maxDate->getTimestamp();
301
-			} else {
302
-				$end = $it->getDtEnd();
303
-				while($it->valid() && $end < $maxDate) {
304
-					$end = $it->getDtEnd();
305
-					$it->next();
306
-
307
-				}
308
-				$lastOccurrence = $end->getTimestamp();
309
-			}
310
-		}
311
-
312
-		return $lastOccurrence;
313
-	}
314
-
315
-
316
-	/**
317
-	 * @param Message $iTipMessage
318
-	 * @return null|Property
319
-	 */
320
-	private function getCurrentAttendee(Message $iTipMessage) {
321
-		/** @var VEvent $vevent */
322
-		$vevent = $iTipMessage->message->VEVENT;
323
-		$attendees = $vevent->select('ATTENDEE');
324
-		foreach ($attendees as $attendee) {
325
-			/** @var Property $attendee */
326
-			if (strcasecmp($attendee->getValue(), $iTipMessage->recipient) === 0) {
327
-				return $attendee;
328
-			}
329
-		}
330
-		return null;
331
-	}
332
-
333
-	/**
334
-	 * @param string $default
335
-	 * @param Property|null $attendee
336
-	 * @return string
337
-	 */
338
-	private function getAttendeeLangOrDefault($default, Property $attendee = null) {
339
-		if ($attendee !== null) {
340
-			$lang = $attendee->offsetGet('LANGUAGE');
341
-			if ($lang instanceof Parameter) {
342
-				return $lang->getValue();
343
-			}
344
-		}
345
-		return $default;
346
-	}
347
-
348
-	/**
349
-	 * @param IL10N $l10n
350
-	 * @param Property $dtstart
351
-	 * @param Property $dtend
352
-	 */
353
-	private function generateWhenString(IL10N $l10n, Property $dtstart, Property $dtend) {
354
-		$isAllDay = $dtstart instanceof Property\ICalendar\Date;
355
-
356
-		/** @var Property\ICalendar\Date | Property\ICalendar\DateTime $dtstart */
357
-		/** @var Property\ICalendar\Date | Property\ICalendar\DateTime $dtend */
358
-		/** @var \DateTimeImmutable $dtstartDt */
359
-		$dtstartDt = $dtstart->getDateTime();
360
-		/** @var \DateTimeImmutable $dtendDt */
361
-		$dtendDt = $dtend->getDateTime();
362
-
363
-		$diff = $dtstartDt->diff($dtendDt);
364
-
365
-		$dtstartDt = new \DateTime($dtstartDt->format(\DateTime::ATOM));
366
-		$dtendDt = new \DateTime($dtendDt->format(\DateTime::ATOM));
367
-
368
-		if ($isAllDay) {
369
-			// One day event
370
-			if ($diff->days === 1) {
371
-				return $l10n->l('date', $dtstartDt, ['width' => 'medium']);
372
-			}
373
-
374
-			//event that spans over multiple days
375
-			$localeStart = $l10n->l('date', $dtstartDt, ['width' => 'medium']);
376
-			$localeEnd = $l10n->l('date', $dtendDt, ['width' => 'medium']);
377
-
378
-			return $localeStart . ' - ' . $localeEnd;
379
-		}
380
-
381
-		/** @var Property\ICalendar\DateTime $dtstart */
382
-		/** @var Property\ICalendar\DateTime $dtend */
383
-		$isFloating = $dtstart->isFloating();
384
-		$startTimezone = $endTimezone = null;
385
-		if (!$isFloating) {
386
-			$prop = $dtstart->offsetGet('TZID');
387
-			if ($prop instanceof Parameter) {
388
-				$startTimezone = $prop->getValue();
389
-			}
390
-
391
-			$prop = $dtend->offsetGet('TZID');
392
-			if ($prop instanceof Parameter) {
393
-				$endTimezone = $prop->getValue();
394
-			}
395
-		}
396
-
397
-		$localeStart = $l10n->l('weekdayName', $dtstartDt, ['width' => 'abbreviated']) . ', ' .
398
-			$l10n->l('datetime', $dtstartDt, ['width' => 'medium|short']);
399
-
400
-		// always show full date with timezone if timezones are different
401
-		if ($startTimezone !== $endTimezone) {
402
-			$localeEnd = $l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
403
-
404
-			return $localeStart . ' (' . $startTimezone . ') - ' .
405
-				$localeEnd . ' (' . $endTimezone . ')';
406
-		}
407
-
408
-		// show only end time if date is the same
409
-		if ($this->isDayEqual($dtstartDt, $dtendDt)) {
410
-			$localeEnd = $l10n->l('time', $dtendDt, ['width' => 'short']);
411
-		} else {
412
-			$localeEnd = $l10n->l('weekdayName', $dtendDt, ['width' => 'abbreviated']) . ', ' .
413
-				$l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
414
-		}
415
-
416
-		return  $localeStart . ' - ' . $localeEnd . ' (' . $startTimezone . ')';
417
-	}
418
-
419
-	/**
420
-	 * @param \DateTime $dtStart
421
-	 * @param \DateTime $dtEnd
422
-	 * @return bool
423
-	 */
424
-	private function isDayEqual(\DateTime $dtStart, \DateTime $dtEnd) {
425
-		return $dtStart->format('Y-m-d') === $dtEnd->format('Y-m-d');
426
-	}
427
-
428
-	/**
429
-	 * @param IEMailTemplate $template
430
-	 * @param IL10N $l10n
431
-	 * @param string $method
432
-	 * @param string $summary
433
-	 * @param string $attendeeName
434
-	 * @param string $inviteeName
435
-	 */
436
-	private function addSubjectAndHeading(IEMailTemplate $template, IL10N $l10n,
437
-										  $method, $summary, $attendeeName, $inviteeName) {
438
-		if ($method === self::METHOD_CANCEL) {
439
-			$template->setSubject('Cancelled: ' . $summary);
440
-			$template->addHeading($l10n->t('Invitation canceled'), $l10n->t('Hello %s,', [$attendeeName]));
441
-			$template->addBodyText($l10n->t('The meeting »%1$s« with %2$s was canceled.', [$summary, $inviteeName]));
442
-		} else if ($method === self::METHOD_REPLY) {
443
-			$template->setSubject('Re: ' . $summary);
444
-			$template->addHeading($l10n->t('Invitation updated'), $l10n->t('Hello %s,', [$attendeeName]));
445
-			$template->addBodyText($l10n->t('The meeting »%1$s« with %2$s was updated.', [$summary, $inviteeName]));
446
-		} else {
447
-			$template->setSubject('Invitation: ' . $summary);
448
-			$template->addHeading($l10n->t('%1$s invited you to »%2$s«', [$inviteeName, $summary]), $l10n->t('Hello %s,', [$attendeeName]));
449
-		}
450
-
451
-	}
452
-
453
-	/**
454
-	 * @param IEMailTemplate $template
455
-	 * @param IL10N $l10n
456
-	 * @param string $time
457
-	 * @param string $location
458
-	 * @param string $description
459
-	 * @param string $url
460
-	 */
461
-	private function addBulletList(IEMailTemplate $template, IL10N $l10n, $time, $location, $description, $url) {
462
-		$template->addBodyListItem($time, $l10n->t('When:'),
463
-			$this->getAbsoluteImagePath('filetypes/text-calendar.svg'));
464
-
465
-		if ($location) {
466
-			$template->addBodyListItem($location, $l10n->t('Where:'),
467
-				$this->getAbsoluteImagePath('filetypes/location.svg'));
468
-		}
469
-		if ($description) {
470
-			$template->addBodyListItem((string)$description, $l10n->t('Description:'),
471
-				$this->getAbsoluteImagePath('filetypes/text.svg'));
472
-		}
473
-		if ($url) {
474
-			$template->addBodyListItem((string)$url, $l10n->t('Link:'),
475
-				$this->getAbsoluteImagePath('filetypes/link.svg'));
476
-		}
477
-	}
478
-
479
-	/**
480
-	 * @param IEMailTemplate $template
481
-	 * @param IL10N $l10n
482
-	 * @param Message $iTipMessage
483
-	 * @param int $lastOccurrence
484
-	 */
485
-	private function addResponseButtons(IEMailTemplate $template, IL10N $l10n,
486
-										Message $iTipMessage, $lastOccurrence) {
487
-		$token = $this->createInvitationToken($iTipMessage, $lastOccurrence);
488
-
489
-		$template->addBodyButtonGroup(
490
-			$l10n->t('Accept'),
491
-			$this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.accept', [
492
-				'token' => $token,
493
-			]),
494
-			$l10n->t('Decline'),
495
-			$this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.decline', [
496
-				'token' => $token,
497
-			])
498
-		);
499
-
500
-		$moreOptionsURL = $this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.options', [
501
-			'token' => $token,
502
-		]);
503
-		$html = vsprintf('<small><a href="%s">%s</a></small>', [
504
-			$moreOptionsURL, $l10n->t('More options …')
505
-		]);
506
-		$text = $l10n->t('More options at %s', [$moreOptionsURL]);
63
+    /** @var string */
64
+    private $userId;
65
+
66
+    /** @var IConfig */
67
+    private $config;
68
+
69
+    /** @var IMailer */
70
+    private $mailer;
71
+
72
+    /** @var ILogger */
73
+    private $logger;
74
+
75
+    /** @var ITimeFactory */
76
+    private $timeFactory;
77
+
78
+    /** @var L10NFactory */
79
+    private $l10nFactory;
80
+
81
+    /** @var IURLGenerator */
82
+    private $urlGenerator;
83
+
84
+    /** @var ISecureRandom */
85
+    private $random;
86
+
87
+    /** @var IDBConnection */
88
+    private $db;
89
+
90
+    /** @var Defaults */
91
+    private $defaults;
92
+
93
+    const MAX_DATE = '2038-01-01';
94
+
95
+    const METHOD_REQUEST = 'request';
96
+    const METHOD_REPLY = 'reply';
97
+    const METHOD_CANCEL = 'cancel';
98
+
99
+    /**
100
+     * @param IConfig $config
101
+     * @param IMailer $mailer
102
+     * @param ILogger $logger
103
+     * @param ITimeFactory $timeFactory
104
+     * @param L10NFactory $l10nFactory
105
+     * @param IUrlGenerator $urlGenerator
106
+     * @param Defaults $defaults
107
+     * @param ISecureRandom $random
108
+     * @param IDBConnection $db
109
+     * @param string $userId
110
+     */
111
+    public function __construct(IConfig $config, IMailer $mailer, ILogger $logger,
112
+                                ITimeFactory $timeFactory, L10NFactory $l10nFactory,
113
+                                IURLGenerator $urlGenerator, Defaults $defaults,
114
+                                ISecureRandom $random, IDBConnection $db, $userId) {
115
+        parent::__construct('');
116
+        $this->userId = $userId;
117
+        $this->config = $config;
118
+        $this->mailer = $mailer;
119
+        $this->logger = $logger;
120
+        $this->timeFactory = $timeFactory;
121
+        $this->l10nFactory = $l10nFactory;
122
+        $this->urlGenerator = $urlGenerator;
123
+        $this->random = $random;
124
+        $this->db = $db;
125
+        $this->defaults = $defaults;
126
+    }
127
+
128
+    /**
129
+     * Event handler for the 'schedule' event.
130
+     *
131
+     * @param Message $iTipMessage
132
+     * @return void
133
+     */
134
+    public function schedule(Message $iTipMessage) {
135
+
136
+        // Not sending any emails if the system considers the update
137
+        // insignificant.
138
+        if (!$iTipMessage->significantChange) {
139
+            if (!$iTipMessage->scheduleStatus) {
140
+                $iTipMessage->scheduleStatus = '1.0;We got the message, but it\'s not significant enough to warrant an email';
141
+            }
142
+            return;
143
+        }
144
+
145
+        $summary = $iTipMessage->message->VEVENT->SUMMARY;
146
+
147
+        if (parse_url($iTipMessage->sender, PHP_URL_SCHEME) !== 'mailto') {
148
+            return;
149
+        }
150
+
151
+        if (parse_url($iTipMessage->recipient, PHP_URL_SCHEME) !== 'mailto') {
152
+            return;
153
+        }
154
+
155
+        // don't send out mails for events that already took place
156
+        $lastOccurrence = $this->getLastOccurrence($iTipMessage->message);
157
+        $currentTime = $this->timeFactory->getTime();
158
+        if ($lastOccurrence < $currentTime) {
159
+            return;
160
+        }
161
+
162
+        // Strip off mailto:
163
+        $sender = substr($iTipMessage->sender, 7);
164
+        $recipient = substr($iTipMessage->recipient, 7);
165
+
166
+        $senderName = $iTipMessage->senderName ?: null;
167
+        $recipientName = $iTipMessage->recipientName ?: null;
168
+
169
+        /** @var VEvent $vevent */
170
+        $vevent = $iTipMessage->message->VEVENT;
171
+
172
+        $attendee = $this->getCurrentAttendee($iTipMessage);
173
+        $defaultLang = $this->config->getUserValue($this->userId, 'core', 'lang', $this->l10nFactory->findLanguage());
174
+        $lang = $this->getAttendeeLangOrDefault($defaultLang, $attendee);
175
+        $l10n = $this->l10nFactory->get('dav', $lang);
176
+
177
+        $meetingAttendeeName = $recipientName ?: $recipient;
178
+        $meetingInviteeName = $senderName ?: $sender;
179
+
180
+        $meetingTitle = $vevent->SUMMARY;
181
+        $meetingDescription = $vevent->DESCRIPTION;
182
+
183
+        $start = $vevent->DTSTART;
184
+        if (isset($vevent->DTEND)) {
185
+            $end = $vevent->DTEND;
186
+        } elseif (isset($vevent->DURATION)) {
187
+            $isFloating = $vevent->DTSTART->isFloating();
188
+            $end = clone $vevent->DTSTART;
189
+            $endDateTime = $end->getDateTime();
190
+            $endDateTime = $endDateTime->add(DateTimeParser::parse($vevent->DURATION->getValue()));
191
+            $end->setDateTime($endDateTime, $isFloating);
192
+        } elseif (!$vevent->DTSTART->hasTime()) {
193
+            $isFloating = $vevent->DTSTART->isFloating();
194
+            $end = clone $vevent->DTSTART;
195
+            $endDateTime = $end->getDateTime();
196
+            $endDateTime = $endDateTime->modify('+1 day');
197
+            $end->setDateTime($endDateTime, $isFloating);
198
+        } else {
199
+            $end = clone $vevent->DTSTART;
200
+        }
201
+
202
+        $meetingWhen = $this->generateWhenString($l10n, $start, $end);
203
+
204
+        $meetingUrl = $vevent->URL;
205
+        $meetingLocation = $vevent->LOCATION;
206
+
207
+        $defaultVal = '--';
208
+
209
+        $method = self::METHOD_REQUEST;
210
+        switch (strtolower($iTipMessage->method)) {
211
+            case self::METHOD_REPLY:
212
+                $method = self::METHOD_REPLY;
213
+                break;
214
+            case self::METHOD_CANCEL:
215
+                $method = self::METHOD_CANCEL;
216
+                break;
217
+        }
218
+
219
+        $data = array(
220
+            'attendee_name' => (string)$meetingAttendeeName ?: $defaultVal,
221
+            'invitee_name' => (string)$meetingInviteeName ?: $defaultVal,
222
+            'meeting_title' => (string)$meetingTitle ?: $defaultVal,
223
+            'meeting_description' => (string)$meetingDescription ?: $defaultVal,
224
+            'meeting_url' => (string)$meetingUrl ?: $defaultVal,
225
+        );
226
+
227
+        $fromEMail = \OCP\Util::getDefaultEmailAddress('invitations-noreply');
228
+        $fromName = $l10n->t('%1$s via %2$s', [$senderName, $this->defaults->getName()]);
229
+
230
+        $message = $this->mailer->createMessage()
231
+            ->setFrom([$fromEMail => $fromName])
232
+            ->setReplyTo([$sender => $senderName])
233
+            ->setTo([$recipient => $recipientName]);
234
+
235
+        $template = $this->mailer->createEMailTemplate('dav.calendarInvite.' . $method, $data);
236
+        $template->addHeader();
237
+
238
+        $this->addSubjectAndHeading($template, $l10n, $method, $summary,
239
+            $meetingAttendeeName, $meetingInviteeName);
240
+        $this->addBulletList($template, $l10n, $meetingWhen, $meetingLocation,
241
+            $meetingDescription, $meetingUrl);
242
+        $this->addResponseButtons($template, $l10n, $iTipMessage, $lastOccurrence);
243
+
244
+        $template->addFooter();
245
+        $message->useTemplate($template);
246
+
247
+        $attachment = $this->mailer->createAttachment(
248
+            $iTipMessage->message->serialize(),
249
+            'event.ics',// TODO(leon): Make file name unique, e.g. add event id
250
+            'text/calendar; method=' . $iTipMessage->method
251
+        );
252
+        $message->attach($attachment);
253
+
254
+        try {
255
+            $failed = $this->mailer->send($message);
256
+            $iTipMessage->scheduleStatus = '1.1; Scheduling message is sent via iMip';
257
+            if ($failed) {
258
+                $this->logger->error('Unable to deliver message to {failed}', ['app' => 'dav', 'failed' =>  implode(', ', $failed)]);
259
+                $iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
260
+            }
261
+        } catch(\Exception $ex) {
262
+            $this->logger->logException($ex, ['app' => 'dav']);
263
+            $iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
264
+        }
265
+    }
266
+
267
+    /**
268
+     * check if event took place in the past already
269
+     * @param VCalendar $vObject
270
+     * @return int
271
+     */
272
+    private function getLastOccurrence(VCalendar $vObject) {
273
+        /** @var VEvent $component */
274
+        $component = $vObject->VEVENT;
275
+
276
+        $firstOccurrence = $component->DTSTART->getDateTime()->getTimeStamp();
277
+        // Finding the last occurrence is a bit harder
278
+        if (!isset($component->RRULE)) {
279
+            if (isset($component->DTEND)) {
280
+                $lastOccurrence = $component->DTEND->getDateTime()->getTimeStamp();
281
+            } elseif (isset($component->DURATION)) {
282
+                /** @var \DateTime $endDate */
283
+                $endDate = clone $component->DTSTART->getDateTime();
284
+                // $component->DTEND->getDateTime() returns DateTimeImmutable
285
+                $endDate = $endDate->add(DateTimeParser::parse($component->DURATION->getValue()));
286
+                $lastOccurrence = $endDate->getTimestamp();
287
+            } elseif (!$component->DTSTART->hasTime()) {
288
+                /** @var \DateTime $endDate */
289
+                $endDate = clone $component->DTSTART->getDateTime();
290
+                // $component->DTSTART->getDateTime() returns DateTimeImmutable
291
+                $endDate = $endDate->modify('+1 day');
292
+                $lastOccurrence = $endDate->getTimestamp();
293
+            } else {
294
+                $lastOccurrence = $firstOccurrence;
295
+            }
296
+        } else {
297
+            $it = new EventIterator($vObject, (string)$component->UID);
298
+            $maxDate = new \DateTime(self::MAX_DATE);
299
+            if ($it->isInfinite()) {
300
+                $lastOccurrence = $maxDate->getTimestamp();
301
+            } else {
302
+                $end = $it->getDtEnd();
303
+                while($it->valid() && $end < $maxDate) {
304
+                    $end = $it->getDtEnd();
305
+                    $it->next();
306
+
307
+                }
308
+                $lastOccurrence = $end->getTimestamp();
309
+            }
310
+        }
311
+
312
+        return $lastOccurrence;
313
+    }
314
+
315
+
316
+    /**
317
+     * @param Message $iTipMessage
318
+     * @return null|Property
319
+     */
320
+    private function getCurrentAttendee(Message $iTipMessage) {
321
+        /** @var VEvent $vevent */
322
+        $vevent = $iTipMessage->message->VEVENT;
323
+        $attendees = $vevent->select('ATTENDEE');
324
+        foreach ($attendees as $attendee) {
325
+            /** @var Property $attendee */
326
+            if (strcasecmp($attendee->getValue(), $iTipMessage->recipient) === 0) {
327
+                return $attendee;
328
+            }
329
+        }
330
+        return null;
331
+    }
332
+
333
+    /**
334
+     * @param string $default
335
+     * @param Property|null $attendee
336
+     * @return string
337
+     */
338
+    private function getAttendeeLangOrDefault($default, Property $attendee = null) {
339
+        if ($attendee !== null) {
340
+            $lang = $attendee->offsetGet('LANGUAGE');
341
+            if ($lang instanceof Parameter) {
342
+                return $lang->getValue();
343
+            }
344
+        }
345
+        return $default;
346
+    }
347
+
348
+    /**
349
+     * @param IL10N $l10n
350
+     * @param Property $dtstart
351
+     * @param Property $dtend
352
+     */
353
+    private function generateWhenString(IL10N $l10n, Property $dtstart, Property $dtend) {
354
+        $isAllDay = $dtstart instanceof Property\ICalendar\Date;
355
+
356
+        /** @var Property\ICalendar\Date | Property\ICalendar\DateTime $dtstart */
357
+        /** @var Property\ICalendar\Date | Property\ICalendar\DateTime $dtend */
358
+        /** @var \DateTimeImmutable $dtstartDt */
359
+        $dtstartDt = $dtstart->getDateTime();
360
+        /** @var \DateTimeImmutable $dtendDt */
361
+        $dtendDt = $dtend->getDateTime();
362
+
363
+        $diff = $dtstartDt->diff($dtendDt);
364
+
365
+        $dtstartDt = new \DateTime($dtstartDt->format(\DateTime::ATOM));
366
+        $dtendDt = new \DateTime($dtendDt->format(\DateTime::ATOM));
367
+
368
+        if ($isAllDay) {
369
+            // One day event
370
+            if ($diff->days === 1) {
371
+                return $l10n->l('date', $dtstartDt, ['width' => 'medium']);
372
+            }
373
+
374
+            //event that spans over multiple days
375
+            $localeStart = $l10n->l('date', $dtstartDt, ['width' => 'medium']);
376
+            $localeEnd = $l10n->l('date', $dtendDt, ['width' => 'medium']);
377
+
378
+            return $localeStart . ' - ' . $localeEnd;
379
+        }
380
+
381
+        /** @var Property\ICalendar\DateTime $dtstart */
382
+        /** @var Property\ICalendar\DateTime $dtend */
383
+        $isFloating = $dtstart->isFloating();
384
+        $startTimezone = $endTimezone = null;
385
+        if (!$isFloating) {
386
+            $prop = $dtstart->offsetGet('TZID');
387
+            if ($prop instanceof Parameter) {
388
+                $startTimezone = $prop->getValue();
389
+            }
390
+
391
+            $prop = $dtend->offsetGet('TZID');
392
+            if ($prop instanceof Parameter) {
393
+                $endTimezone = $prop->getValue();
394
+            }
395
+        }
396
+
397
+        $localeStart = $l10n->l('weekdayName', $dtstartDt, ['width' => 'abbreviated']) . ', ' .
398
+            $l10n->l('datetime', $dtstartDt, ['width' => 'medium|short']);
399
+
400
+        // always show full date with timezone if timezones are different
401
+        if ($startTimezone !== $endTimezone) {
402
+            $localeEnd = $l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
403
+
404
+            return $localeStart . ' (' . $startTimezone . ') - ' .
405
+                $localeEnd . ' (' . $endTimezone . ')';
406
+        }
407
+
408
+        // show only end time if date is the same
409
+        if ($this->isDayEqual($dtstartDt, $dtendDt)) {
410
+            $localeEnd = $l10n->l('time', $dtendDt, ['width' => 'short']);
411
+        } else {
412
+            $localeEnd = $l10n->l('weekdayName', $dtendDt, ['width' => 'abbreviated']) . ', ' .
413
+                $l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
414
+        }
415
+
416
+        return  $localeStart . ' - ' . $localeEnd . ' (' . $startTimezone . ')';
417
+    }
418
+
419
+    /**
420
+     * @param \DateTime $dtStart
421
+     * @param \DateTime $dtEnd
422
+     * @return bool
423
+     */
424
+    private function isDayEqual(\DateTime $dtStart, \DateTime $dtEnd) {
425
+        return $dtStart->format('Y-m-d') === $dtEnd->format('Y-m-d');
426
+    }
427
+
428
+    /**
429
+     * @param IEMailTemplate $template
430
+     * @param IL10N $l10n
431
+     * @param string $method
432
+     * @param string $summary
433
+     * @param string $attendeeName
434
+     * @param string $inviteeName
435
+     */
436
+    private function addSubjectAndHeading(IEMailTemplate $template, IL10N $l10n,
437
+                                            $method, $summary, $attendeeName, $inviteeName) {
438
+        if ($method === self::METHOD_CANCEL) {
439
+            $template->setSubject('Cancelled: ' . $summary);
440
+            $template->addHeading($l10n->t('Invitation canceled'), $l10n->t('Hello %s,', [$attendeeName]));
441
+            $template->addBodyText($l10n->t('The meeting »%1$s« with %2$s was canceled.', [$summary, $inviteeName]));
442
+        } else if ($method === self::METHOD_REPLY) {
443
+            $template->setSubject('Re: ' . $summary);
444
+            $template->addHeading($l10n->t('Invitation updated'), $l10n->t('Hello %s,', [$attendeeName]));
445
+            $template->addBodyText($l10n->t('The meeting »%1$s« with %2$s was updated.', [$summary, $inviteeName]));
446
+        } else {
447
+            $template->setSubject('Invitation: ' . $summary);
448
+            $template->addHeading($l10n->t('%1$s invited you to »%2$s«', [$inviteeName, $summary]), $l10n->t('Hello %s,', [$attendeeName]));
449
+        }
450
+
451
+    }
452
+
453
+    /**
454
+     * @param IEMailTemplate $template
455
+     * @param IL10N $l10n
456
+     * @param string $time
457
+     * @param string $location
458
+     * @param string $description
459
+     * @param string $url
460
+     */
461
+    private function addBulletList(IEMailTemplate $template, IL10N $l10n, $time, $location, $description, $url) {
462
+        $template->addBodyListItem($time, $l10n->t('When:'),
463
+            $this->getAbsoluteImagePath('filetypes/text-calendar.svg'));
464
+
465
+        if ($location) {
466
+            $template->addBodyListItem($location, $l10n->t('Where:'),
467
+                $this->getAbsoluteImagePath('filetypes/location.svg'));
468
+        }
469
+        if ($description) {
470
+            $template->addBodyListItem((string)$description, $l10n->t('Description:'),
471
+                $this->getAbsoluteImagePath('filetypes/text.svg'));
472
+        }
473
+        if ($url) {
474
+            $template->addBodyListItem((string)$url, $l10n->t('Link:'),
475
+                $this->getAbsoluteImagePath('filetypes/link.svg'));
476
+        }
477
+    }
478
+
479
+    /**
480
+     * @param IEMailTemplate $template
481
+     * @param IL10N $l10n
482
+     * @param Message $iTipMessage
483
+     * @param int $lastOccurrence
484
+     */
485
+    private function addResponseButtons(IEMailTemplate $template, IL10N $l10n,
486
+                                        Message $iTipMessage, $lastOccurrence) {
487
+        $token = $this->createInvitationToken($iTipMessage, $lastOccurrence);
488
+
489
+        $template->addBodyButtonGroup(
490
+            $l10n->t('Accept'),
491
+            $this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.accept', [
492
+                'token' => $token,
493
+            ]),
494
+            $l10n->t('Decline'),
495
+            $this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.decline', [
496
+                'token' => $token,
497
+            ])
498
+        );
499
+
500
+        $moreOptionsURL = $this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.options', [
501
+            'token' => $token,
502
+        ]);
503
+        $html = vsprintf('<small><a href="%s">%s</a></small>', [
504
+            $moreOptionsURL, $l10n->t('More options …')
505
+        ]);
506
+        $text = $l10n->t('More options at %s', [$moreOptionsURL]);
507 507
 		
508
-		$template->addBodyText($html, $text);
509
-	}
510
-
511
-	/**
512
-	 * @param string $path
513
-	 * @return string
514
-	 */
515
-	private function getAbsoluteImagePath($path) {
516
-		return $this->urlGenerator->getAbsoluteURL(
517
-			$this->urlGenerator->imagePath('core', $path)
518
-		);
519
-	}
520
-
521
-	/**
522
-	 * @param Message $iTipMessage
523
-	 * @param int $lastOccurrence
524
-	 * @return string
525
-	 */
526
-	private function createInvitationToken(Message $iTipMessage, $lastOccurrence):string {
527
-		$token = $this->random->generate(60, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS);
528
-
529
-		/** @var VEvent $vevent */
530
-		$vevent = $iTipMessage->message->VEVENT;
531
-		$attendee = $iTipMessage->recipient;
532
-		$organizer = $iTipMessage->sender;
533
-		$sequence = $iTipMessage->sequence;
534
-		$recurrenceId = isset($vevent->{'RECURRENCE-ID'}) ?
535
-			$vevent->{'RECURRENCE-ID'}->serialize() : null;
536
-		$uid = $vevent->{'UID'};
537
-
538
-		$query = $this->db->getQueryBuilder();
539
-		$query->insert('calendar_invitations')
540
-			->values([
541
-				'token' => $query->createNamedParameter($token),
542
-				'attendee' => $query->createNamedParameter($attendee),
543
-				'organizer' => $query->createNamedParameter($organizer),
544
-				'sequence' => $query->createNamedParameter($sequence),
545
-				'recurrenceid' => $query->createNamedParameter($recurrenceId),
546
-				'expiration' => $query->createNamedParameter($lastOccurrence),
547
-				'uid' => $query->createNamedParameter($uid)
548
-			])
549
-			->execute();
550
-
551
-		return $token;
552
-	}
508
+        $template->addBodyText($html, $text);
509
+    }
510
+
511
+    /**
512
+     * @param string $path
513
+     * @return string
514
+     */
515
+    private function getAbsoluteImagePath($path) {
516
+        return $this->urlGenerator->getAbsoluteURL(
517
+            $this->urlGenerator->imagePath('core', $path)
518
+        );
519
+    }
520
+
521
+    /**
522
+     * @param Message $iTipMessage
523
+     * @param int $lastOccurrence
524
+     * @return string
525
+     */
526
+    private function createInvitationToken(Message $iTipMessage, $lastOccurrence):string {
527
+        $token = $this->random->generate(60, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS);
528
+
529
+        /** @var VEvent $vevent */
530
+        $vevent = $iTipMessage->message->VEVENT;
531
+        $attendee = $iTipMessage->recipient;
532
+        $organizer = $iTipMessage->sender;
533
+        $sequence = $iTipMessage->sequence;
534
+        $recurrenceId = isset($vevent->{'RECURRENCE-ID'}) ?
535
+            $vevent->{'RECURRENCE-ID'}->serialize() : null;
536
+        $uid = $vevent->{'UID'};
537
+
538
+        $query = $this->db->getQueryBuilder();
539
+        $query->insert('calendar_invitations')
540
+            ->values([
541
+                'token' => $query->createNamedParameter($token),
542
+                'attendee' => $query->createNamedParameter($attendee),
543
+                'organizer' => $query->createNamedParameter($organizer),
544
+                'sequence' => $query->createNamedParameter($sequence),
545
+                'recurrenceid' => $query->createNamedParameter($recurrenceId),
546
+                'expiration' => $query->createNamedParameter($lastOccurrence),
547
+                'uid' => $query->createNamedParameter($uid)
548
+            ])
549
+            ->execute();
550
+
551
+        return $token;
552
+    }
553 553
 }
Please login to merge, or discard this patch.
Spacing   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -217,11 +217,11 @@  discard block
 block discarded – undo
217 217
 		}
218 218
 
219 219
 		$data = array(
220
-			'attendee_name' => (string)$meetingAttendeeName ?: $defaultVal,
221
-			'invitee_name' => (string)$meetingInviteeName ?: $defaultVal,
222
-			'meeting_title' => (string)$meetingTitle ?: $defaultVal,
223
-			'meeting_description' => (string)$meetingDescription ?: $defaultVal,
224
-			'meeting_url' => (string)$meetingUrl ?: $defaultVal,
220
+			'attendee_name' => (string) $meetingAttendeeName ?: $defaultVal,
221
+			'invitee_name' => (string) $meetingInviteeName ?: $defaultVal,
222
+			'meeting_title' => (string) $meetingTitle ?: $defaultVal,
223
+			'meeting_description' => (string) $meetingDescription ?: $defaultVal,
224
+			'meeting_url' => (string) $meetingUrl ?: $defaultVal,
225 225
 		);
226 226
 
227 227
 		$fromEMail = \OCP\Util::getDefaultEmailAddress('invitations-noreply');
@@ -232,7 +232,7 @@  discard block
 block discarded – undo
232 232
 			->setReplyTo([$sender => $senderName])
233 233
 			->setTo([$recipient => $recipientName]);
234 234
 
235
-		$template = $this->mailer->createEMailTemplate('dav.calendarInvite.' . $method, $data);
235
+		$template = $this->mailer->createEMailTemplate('dav.calendarInvite.'.$method, $data);
236 236
 		$template->addHeader();
237 237
 
238 238
 		$this->addSubjectAndHeading($template, $l10n, $method, $summary,
@@ -246,8 +246,8 @@  discard block
 block discarded – undo
246 246
 
247 247
 		$attachment = $this->mailer->createAttachment(
248 248
 			$iTipMessage->message->serialize(),
249
-			'event.ics',// TODO(leon): Make file name unique, e.g. add event id
250
-			'text/calendar; method=' . $iTipMessage->method
249
+			'event.ics', // TODO(leon): Make file name unique, e.g. add event id
250
+			'text/calendar; method='.$iTipMessage->method
251 251
 		);
252 252
 		$message->attach($attachment);
253 253
 
@@ -258,7 +258,7 @@  discard block
 block discarded – undo
258 258
 				$this->logger->error('Unable to deliver message to {failed}', ['app' => 'dav', 'failed' =>  implode(', ', $failed)]);
259 259
 				$iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
260 260
 			}
261
-		} catch(\Exception $ex) {
261
+		} catch (\Exception $ex) {
262 262
 			$this->logger->logException($ex, ['app' => 'dav']);
263 263
 			$iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
264 264
 		}
@@ -294,13 +294,13 @@  discard block
 block discarded – undo
294 294
 				$lastOccurrence = $firstOccurrence;
295 295
 			}
296 296
 		} else {
297
-			$it = new EventIterator($vObject, (string)$component->UID);
297
+			$it = new EventIterator($vObject, (string) $component->UID);
298 298
 			$maxDate = new \DateTime(self::MAX_DATE);
299 299
 			if ($it->isInfinite()) {
300 300
 				$lastOccurrence = $maxDate->getTimestamp();
301 301
 			} else {
302 302
 				$end = $it->getDtEnd();
303
-				while($it->valid() && $end < $maxDate) {
303
+				while ($it->valid() && $end < $maxDate) {
304 304
 					$end = $it->getDtEnd();
305 305
 					$it->next();
306 306
 
@@ -375,7 +375,7 @@  discard block
 block discarded – undo
375 375
 			$localeStart = $l10n->l('date', $dtstartDt, ['width' => 'medium']);
376 376
 			$localeEnd = $l10n->l('date', $dtendDt, ['width' => 'medium']);
377 377
 
378
-			return $localeStart . ' - ' . $localeEnd;
378
+			return $localeStart.' - '.$localeEnd;
379 379
 		}
380 380
 
381 381
 		/** @var Property\ICalendar\DateTime $dtstart */
@@ -394,26 +394,26 @@  discard block
 block discarded – undo
394 394
 			}
395 395
 		}
396 396
 
397
-		$localeStart = $l10n->l('weekdayName', $dtstartDt, ['width' => 'abbreviated']) . ', ' .
397
+		$localeStart = $l10n->l('weekdayName', $dtstartDt, ['width' => 'abbreviated']).', '.
398 398
 			$l10n->l('datetime', $dtstartDt, ['width' => 'medium|short']);
399 399
 
400 400
 		// always show full date with timezone if timezones are different
401 401
 		if ($startTimezone !== $endTimezone) {
402 402
 			$localeEnd = $l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
403 403
 
404
-			return $localeStart . ' (' . $startTimezone . ') - ' .
405
-				$localeEnd . ' (' . $endTimezone . ')';
404
+			return $localeStart.' ('.$startTimezone.') - '.
405
+				$localeEnd.' ('.$endTimezone.')';
406 406
 		}
407 407
 
408 408
 		// show only end time if date is the same
409 409
 		if ($this->isDayEqual($dtstartDt, $dtendDt)) {
410 410
 			$localeEnd = $l10n->l('time', $dtendDt, ['width' => 'short']);
411 411
 		} else {
412
-			$localeEnd = $l10n->l('weekdayName', $dtendDt, ['width' => 'abbreviated']) . ', ' .
412
+			$localeEnd = $l10n->l('weekdayName', $dtendDt, ['width' => 'abbreviated']).', '.
413 413
 				$l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
414 414
 		}
415 415
 
416
-		return  $localeStart . ' - ' . $localeEnd . ' (' . $startTimezone . ')';
416
+		return  $localeStart.' - '.$localeEnd.' ('.$startTimezone.')';
417 417
 	}
418 418
 
419 419
 	/**
@@ -436,15 +436,15 @@  discard block
 block discarded – undo
436 436
 	private function addSubjectAndHeading(IEMailTemplate $template, IL10N $l10n,
437 437
 										  $method, $summary, $attendeeName, $inviteeName) {
438 438
 		if ($method === self::METHOD_CANCEL) {
439
-			$template->setSubject('Cancelled: ' . $summary);
439
+			$template->setSubject('Cancelled: '.$summary);
440 440
 			$template->addHeading($l10n->t('Invitation canceled'), $l10n->t('Hello %s,', [$attendeeName]));
441 441
 			$template->addBodyText($l10n->t('The meeting »%1$s« with %2$s was canceled.', [$summary, $inviteeName]));
442 442
 		} else if ($method === self::METHOD_REPLY) {
443
-			$template->setSubject('Re: ' . $summary);
443
+			$template->setSubject('Re: '.$summary);
444 444
 			$template->addHeading($l10n->t('Invitation updated'), $l10n->t('Hello %s,', [$attendeeName]));
445 445
 			$template->addBodyText($l10n->t('The meeting »%1$s« with %2$s was updated.', [$summary, $inviteeName]));
446 446
 		} else {
447
-			$template->setSubject('Invitation: ' . $summary);
447
+			$template->setSubject('Invitation: '.$summary);
448 448
 			$template->addHeading($l10n->t('%1$s invited you to »%2$s«', [$inviteeName, $summary]), $l10n->t('Hello %s,', [$attendeeName]));
449 449
 		}
450 450
 
@@ -467,11 +467,11 @@  discard block
 block discarded – undo
467 467
 				$this->getAbsoluteImagePath('filetypes/location.svg'));
468 468
 		}
469 469
 		if ($description) {
470
-			$template->addBodyListItem((string)$description, $l10n->t('Description:'),
470
+			$template->addBodyListItem((string) $description, $l10n->t('Description:'),
471 471
 				$this->getAbsoluteImagePath('filetypes/text.svg'));
472 472
 		}
473 473
 		if ($url) {
474
-			$template->addBodyListItem((string)$url, $l10n->t('Link:'),
474
+			$template->addBodyListItem((string) $url, $l10n->t('Link:'),
475 475
 				$this->getAbsoluteImagePath('filetypes/link.svg'));
476 476
 		}
477 477
 	}
@@ -524,7 +524,7 @@  discard block
 block discarded – undo
524 524
 	 * @return string
525 525
 	 */
526 526
 	private function createInvitationToken(Message $iTipMessage, $lastOccurrence):string {
527
-		$token = $this->random->generate(60, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS);
527
+		$token = $this->random->generate(60, ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_DIGITS);
528 528
 
529 529
 		/** @var VEvent $vevent */
530 530
 		$vevent = $iTipMessage->message->VEVENT;
Please login to merge, or discard this patch.
apps/admin_audit/lib/Actions/AppManagement.php 1 patch
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -26,34 +26,34 @@
 block discarded – undo
26 26
 
27 27
 class AppManagement extends Action {
28 28
 
29
-	/**
30
-	 * @param string $appName
31
-	 */
32
-	public function enableApp(string $appName) {
33
-		$this->log('App "%s" enabled',
34
-			['app' => $appName],
35
-			['app']
36
-		);
37
-	}
29
+    /**
30
+     * @param string $appName
31
+     */
32
+    public function enableApp(string $appName) {
33
+        $this->log('App "%s" enabled',
34
+            ['app' => $appName],
35
+            ['app']
36
+        );
37
+    }
38 38
 
39
-	/**
40
-	 * @param string $appName
41
-	 * @param string[] $groups
42
-	 */
43
-	public function enableAppForGroups(string $appName, array $groups) {
44
-		$this->log('App "%1$s" enabled for groups: %2$s',
45
-			['app' => $appName, 'groups' => implode(', ', $groups)],
46
-			['app', 'groups']
47
-		);
48
-	}
39
+    /**
40
+     * @param string $appName
41
+     * @param string[] $groups
42
+     */
43
+    public function enableAppForGroups(string $appName, array $groups) {
44
+        $this->log('App "%1$s" enabled for groups: %2$s',
45
+            ['app' => $appName, 'groups' => implode(', ', $groups)],
46
+            ['app', 'groups']
47
+        );
48
+    }
49 49
 
50
-	/**
51
-	 * @param string $appName
52
-	 */
53
-	public function disableApp(string $appName) {
54
-		$this->log('App "%s" disabled',
55
-			['app' => $appName],
56
-			['app']
57
-		);
58
-	}
50
+    /**
51
+     * @param string $appName
52
+     */
53
+    public function disableApp(string $appName) {
54
+        $this->log('App "%s" disabled',
55
+            ['app' => $appName],
56
+            ['app']
57
+        );
58
+    }
59 59
 }
Please login to merge, or discard this patch.
apps/files/templates/appnavigation.php 1 patch
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -3,24 +3,24 @@  discard block
 block discarded – undo
3 3
 
4 4
 		<?php
5 5
 
6
-		$pinned = 0;
7
-		foreach ($_['navigationItems'] as $item) {
8
-			$pinned = NavigationListElements($item, $l, $pinned);
9
-		}
10
-		?>
6
+        $pinned = 0;
7
+        foreach ($_['navigationItems'] as $item) {
8
+            $pinned = NavigationListElements($item, $l, $pinned);
9
+        }
10
+        ?>
11 11
 
12 12
 		<li id="quota"
13 13
 			class="pinned <?php p($pinned === 0 ? 'first-pinned ' : '') ?><?php
14
-			if ($_['quota'] !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
15
-			?>has-tooltip" title="<?php p($_['usage_relative'] . '%');
16
-		} ?>">
14
+            if ($_['quota'] !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
15
+            ?>has-tooltip" title="<?php p($_['usage_relative'] . '%');
16
+        } ?>">
17 17
 			<a href="#" class="icon-quota svg">
18 18
 				<p id="quotatext"><?php
19
-					if ($_['quota'] !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
20
-						p($l->t('%1$s of %2$s used', [$_['usage'], $_['total_space']]));
21
-					} else {
22
-						p($l->t('%s used', [$_['usage']]));
23
-					} ?></p>
19
+                    if ($_['quota'] !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
20
+                        p($l->t('%1$s of %2$s used', [$_['usage'], $_['total_space']]));
21
+                    } else {
22
+                        p($l->t('%s used', [$_['usage']]));
23
+                    } ?></p>
24 24
 				<div class="quota-container">
25 25
 					<progress value="<?php p($_['usage_relative']); ?>"
26 26
 							  max="100"
@@ -64,8 +64,8 @@  discard block
 block discarded – undo
64 64
  * @return int Returns the pinned value
65 65
  */
66 66
 function NavigationListElements($item, $l, $pinned) {
67
-	strpos($item['classes'] ?? '', 'pinned') !== false ? $pinned++ : '';
68
-	?>
67
+    strpos($item['classes'] ?? '', 'pinned') !== false ? $pinned++ : '';
68
+    ?>
69 69
 	<li
70 70
 		data-id="<?php p($item['id']) ?>"
71 71
 		<?php if (isset($item['dir'])) { ?> data-dir="<?php p($item['dir']); ?>" <?php } ?>
@@ -82,23 +82,23 @@  discard block
 block discarded – undo
82 82
 
83 83
 
84 84
 		<?php
85
-		NavigationElementMenu($item);
86
-		if (isset($item['sublist'])) {
87
-			?>
85
+        NavigationElementMenu($item);
86
+        if (isset($item['sublist'])) {
87
+            ?>
88 88
 			<button class="collapse app-navigation-noclose" <?php if (sizeof($item['sublist']) == 0) { ?> style="display: none" <?php } ?>></button>
89 89
 			<ul id="sublist-<?php p($item['id']); ?>">
90 90
 				<?php
91
-				foreach ($item['sublist'] as $item) {
92
-					$pinned = NavigationListElements($item, $l, $pinned);
93
-				}
94
-				?>
91
+                foreach ($item['sublist'] as $item) {
92
+                    $pinned = NavigationListElements($item, $l, $pinned);
93
+                }
94
+                ?>
95 95
 			</ul>
96 96
 		<?php } ?>
97 97
 	</li>
98 98
 
99 99
 
100 100
 	<?php
101
-	return $pinned;
101
+    return $pinned;
102 102
 }
103 103
 
104 104
 /**
@@ -109,8 +109,8 @@  discard block
 block discarded – undo
109 109
  * @return void
110 110
  */
111 111
 function NavigationElementMenu($item) {
112
-	if (isset($item['menubuttons']) && $item['menubuttons'] === 'true') {
113
-		?>
112
+    if (isset($item['menubuttons']) && $item['menubuttons'] === 'true') {
113
+        ?>
114 114
 		<div id="dotmenu-<?php p($item['id']); ?>"
115 115
 			 class="app-navigation-entry-utils" <?php if (isset($item['enableMenuButton']) && $item['enableMenuButton'] === 0) { ?> style="display: none"<?php } ?>>
116 116
 			<ul>
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/FederatedShareProvider.php 2 patches
Indentation   +1030 added lines, -1030 removed lines patch added patch discarded remove patch
@@ -55,1044 +55,1044 @@
 block discarded – undo
55 55
  */
56 56
 class FederatedShareProvider implements IShareProvider {
57 57
 
58
-	const SHARE_TYPE_REMOTE = 6;
59
-
60
-	/** @var IDBConnection */
61
-	private $dbConnection;
62
-
63
-	/** @var AddressHandler */
64
-	private $addressHandler;
65
-
66
-	/** @var Notifications */
67
-	private $notifications;
68
-
69
-	/** @var TokenHandler */
70
-	private $tokenHandler;
71
-
72
-	/** @var IL10N */
73
-	private $l;
74
-
75
-	/** @var ILogger */
76
-	private $logger;
77
-
78
-	/** @var IRootFolder */
79
-	private $rootFolder;
80
-
81
-	/** @var IConfig */
82
-	private $config;
83
-
84
-	/** @var string */
85
-	private $externalShareTable = 'share_external';
86
-
87
-	/** @var IUserManager */
88
-	private $userManager;
89
-
90
-	/** @var ICloudIdManager */
91
-	private $cloudIdManager;
92
-
93
-	/** @var \OCP\GlobalScale\IConfig */
94
-	private $gsConfig;
95
-
96
-	/** @var ICloudFederationProviderManager */
97
-	private $cloudFederationProviderManager;
98
-
99
-	/** @var array list of supported share types */
100
-	private $supportedShareType = [\OCP\Share::SHARE_TYPE_REMOTE_GROUP, \OCP\Share::SHARE_TYPE_REMOTE];
101
-
102
-	/**
103
-	 * DefaultShareProvider constructor.
104
-	 *
105
-	 * @param IDBConnection $connection
106
-	 * @param AddressHandler $addressHandler
107
-	 * @param Notifications $notifications
108
-	 * @param TokenHandler $tokenHandler
109
-	 * @param IL10N $l10n
110
-	 * @param ILogger $logger
111
-	 * @param IRootFolder $rootFolder
112
-	 * @param IConfig $config
113
-	 * @param IUserManager $userManager
114
-	 * @param ICloudIdManager $cloudIdManager
115
-	 * @param \OCP\GlobalScale\IConfig $globalScaleConfig
116
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
117
-	 */
118
-	public function __construct(
119
-			IDBConnection $connection,
120
-			AddressHandler $addressHandler,
121
-			Notifications $notifications,
122
-			TokenHandler $tokenHandler,
123
-			IL10N $l10n,
124
-			ILogger $logger,
125
-			IRootFolder $rootFolder,
126
-			IConfig $config,
127
-			IUserManager $userManager,
128
-			ICloudIdManager $cloudIdManager,
129
-			\OCP\GlobalScale\IConfig $globalScaleConfig,
130
-			ICloudFederationProviderManager $cloudFederationProviderManager
131
-	) {
132
-		$this->dbConnection = $connection;
133
-		$this->addressHandler = $addressHandler;
134
-		$this->notifications = $notifications;
135
-		$this->tokenHandler = $tokenHandler;
136
-		$this->l = $l10n;
137
-		$this->logger = $logger;
138
-		$this->rootFolder = $rootFolder;
139
-		$this->config = $config;
140
-		$this->userManager = $userManager;
141
-		$this->cloudIdManager = $cloudIdManager;
142
-		$this->gsConfig = $globalScaleConfig;
143
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
144
-	}
145
-
146
-	/**
147
-	 * Return the identifier of this provider.
148
-	 *
149
-	 * @return string Containing only [a-zA-Z0-9]
150
-	 */
151
-	public function identifier() {
152
-		return 'ocFederatedSharing';
153
-	}
154
-
155
-	/**
156
-	 * Share a path
157
-	 *
158
-	 * @param IShare $share
159
-	 * @return IShare The share object
160
-	 * @throws ShareNotFound
161
-	 * @throws \Exception
162
-	 */
163
-	public function create(IShare $share) {
164
-
165
-		$shareWith = $share->getSharedWith();
166
-		$itemSource = $share->getNodeId();
167
-		$itemType = $share->getNodeType();
168
-		$permissions = $share->getPermissions();
169
-		$sharedBy = $share->getSharedBy();
170
-		$shareType = $share->getShareType();
171
-
172
-		if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP &&
173
-			!$this->isOutgoingServer2serverGroupShareEnabled()
174
-		) {
175
-			$message = 'It is not allowed to send federated group shares from this server.';
176
-			$message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
177
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
178
-			throw new \Exception($message_t);
179
-		}
180
-
181
-		/*
58
+    const SHARE_TYPE_REMOTE = 6;
59
+
60
+    /** @var IDBConnection */
61
+    private $dbConnection;
62
+
63
+    /** @var AddressHandler */
64
+    private $addressHandler;
65
+
66
+    /** @var Notifications */
67
+    private $notifications;
68
+
69
+    /** @var TokenHandler */
70
+    private $tokenHandler;
71
+
72
+    /** @var IL10N */
73
+    private $l;
74
+
75
+    /** @var ILogger */
76
+    private $logger;
77
+
78
+    /** @var IRootFolder */
79
+    private $rootFolder;
80
+
81
+    /** @var IConfig */
82
+    private $config;
83
+
84
+    /** @var string */
85
+    private $externalShareTable = 'share_external';
86
+
87
+    /** @var IUserManager */
88
+    private $userManager;
89
+
90
+    /** @var ICloudIdManager */
91
+    private $cloudIdManager;
92
+
93
+    /** @var \OCP\GlobalScale\IConfig */
94
+    private $gsConfig;
95
+
96
+    /** @var ICloudFederationProviderManager */
97
+    private $cloudFederationProviderManager;
98
+
99
+    /** @var array list of supported share types */
100
+    private $supportedShareType = [\OCP\Share::SHARE_TYPE_REMOTE_GROUP, \OCP\Share::SHARE_TYPE_REMOTE];
101
+
102
+    /**
103
+     * DefaultShareProvider constructor.
104
+     *
105
+     * @param IDBConnection $connection
106
+     * @param AddressHandler $addressHandler
107
+     * @param Notifications $notifications
108
+     * @param TokenHandler $tokenHandler
109
+     * @param IL10N $l10n
110
+     * @param ILogger $logger
111
+     * @param IRootFolder $rootFolder
112
+     * @param IConfig $config
113
+     * @param IUserManager $userManager
114
+     * @param ICloudIdManager $cloudIdManager
115
+     * @param \OCP\GlobalScale\IConfig $globalScaleConfig
116
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
117
+     */
118
+    public function __construct(
119
+            IDBConnection $connection,
120
+            AddressHandler $addressHandler,
121
+            Notifications $notifications,
122
+            TokenHandler $tokenHandler,
123
+            IL10N $l10n,
124
+            ILogger $logger,
125
+            IRootFolder $rootFolder,
126
+            IConfig $config,
127
+            IUserManager $userManager,
128
+            ICloudIdManager $cloudIdManager,
129
+            \OCP\GlobalScale\IConfig $globalScaleConfig,
130
+            ICloudFederationProviderManager $cloudFederationProviderManager
131
+    ) {
132
+        $this->dbConnection = $connection;
133
+        $this->addressHandler = $addressHandler;
134
+        $this->notifications = $notifications;
135
+        $this->tokenHandler = $tokenHandler;
136
+        $this->l = $l10n;
137
+        $this->logger = $logger;
138
+        $this->rootFolder = $rootFolder;
139
+        $this->config = $config;
140
+        $this->userManager = $userManager;
141
+        $this->cloudIdManager = $cloudIdManager;
142
+        $this->gsConfig = $globalScaleConfig;
143
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
144
+    }
145
+
146
+    /**
147
+     * Return the identifier of this provider.
148
+     *
149
+     * @return string Containing only [a-zA-Z0-9]
150
+     */
151
+    public function identifier() {
152
+        return 'ocFederatedSharing';
153
+    }
154
+
155
+    /**
156
+     * Share a path
157
+     *
158
+     * @param IShare $share
159
+     * @return IShare The share object
160
+     * @throws ShareNotFound
161
+     * @throws \Exception
162
+     */
163
+    public function create(IShare $share) {
164
+
165
+        $shareWith = $share->getSharedWith();
166
+        $itemSource = $share->getNodeId();
167
+        $itemType = $share->getNodeType();
168
+        $permissions = $share->getPermissions();
169
+        $sharedBy = $share->getSharedBy();
170
+        $shareType = $share->getShareType();
171
+
172
+        if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP &&
173
+            !$this->isOutgoingServer2serverGroupShareEnabled()
174
+        ) {
175
+            $message = 'It is not allowed to send federated group shares from this server.';
176
+            $message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
177
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
178
+            throw new \Exception($message_t);
179
+        }
180
+
181
+        /*
182 182
 		 * Check if file is not already shared with the remote user
183 183
 		 */
184
-		$alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
185
-		$alreadySharedGroup = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
186
-		if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
187
-			$message = 'Sharing %1$s failed, because this item is already shared with %2$s';
188
-			$message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with %2$s', array($share->getNode()->getName(), $shareWith));
189
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
190
-			throw new \Exception($message_t);
191
-		}
192
-
193
-
194
-		// don't allow federated shares if source and target server are the same
195
-		$cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
196
-		$currentServer = $this->addressHandler->generateRemoteURL();
197
-		$currentUser = $sharedBy;
198
-		if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
199
-			$message = 'Not allowed to create a federated share with the same user.';
200
-			$message_t = $this->l->t('Not allowed to create a federated share with the same user');
201
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
202
-			throw new \Exception($message_t);
203
-		}
204
-
205
-
206
-		$share->setSharedWith($cloudId->getId());
207
-
208
-		try {
209
-			$remoteShare = $this->getShareFromExternalShareTable($share);
210
-		} catch (ShareNotFound $e) {
211
-			$remoteShare = null;
212
-		}
213
-
214
-		if ($remoteShare) {
215
-			try {
216
-				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
217
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
218
-				$share->setId($shareId);
219
-				list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
220
-				// remote share was create successfully if we get a valid token as return
221
-				$send = is_string($token) && $token !== '';
222
-			} catch (\Exception $e) {
223
-				// fall back to old re-share behavior if the remote server
224
-				// doesn't support flat re-shares (was introduced with Nextcloud 9.1)
225
-				$this->removeShareFromTable($share);
226
-				$shareId = $this->createFederatedShare($share);
227
-			}
228
-			if ($send) {
229
-				$this->updateSuccessfulReshare($shareId, $token);
230
-				$this->storeRemoteId($shareId, $remoteId);
231
-			} else {
232
-				$this->removeShareFromTable($share);
233
-				$message_t = $this->l->t('File is already shared with %s', [$shareWith]);
234
-				throw new \Exception($message_t);
235
-			}
236
-
237
-		} else {
238
-			$shareId = $this->createFederatedShare($share);
239
-		}
240
-
241
-		$data = $this->getRawShare($shareId);
242
-		return $this->createShareObject($data);
243
-	}
244
-
245
-	/**
246
-	 * create federated share and inform the recipient
247
-	 *
248
-	 * @param IShare $share
249
-	 * @return int
250
-	 * @throws ShareNotFound
251
-	 * @throws \Exception
252
-	 */
253
-	protected function createFederatedShare(IShare $share) {
254
-		$token = $this->tokenHandler->generateToken();
255
-		$shareId = $this->addShareToDB(
256
-			$share->getNodeId(),
257
-			$share->getNodeType(),
258
-			$share->getSharedWith(),
259
-			$share->getSharedBy(),
260
-			$share->getShareOwner(),
261
-			$share->getPermissions(),
262
-			$token,
263
-			$share->getShareType()
264
-		);
265
-
266
-		$failure = false;
267
-
268
-		try {
269
-			$sharedByFederatedId = $share->getSharedBy();
270
-			if ($this->userManager->userExists($sharedByFederatedId)) {
271
-				$cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
272
-				$sharedByFederatedId = $cloudId->getId();
273
-			}
274
-			$ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
275
-			$send = $this->notifications->sendRemoteShare(
276
-				$token,
277
-				$share->getSharedWith(),
278
-				$share->getNode()->getName(),
279
-				$shareId,
280
-				$share->getShareOwner(),
281
-				$ownerCloudId->getId(),
282
-				$share->getSharedBy(),
283
-				$sharedByFederatedId,
284
-				$share->getShareType()
285
-			);
286
-
287
-			if ($send === false) {
288
-				$failure = true;
289
-			}
290
-		} catch (\Exception $e) {
291
-			$this->logger->logException($e, [
292
-				'message' => 'Failed to notify remote server of federated share, removing share.',
293
-				'level' => ILogger::ERROR,
294
-				'app' => 'federatedfilesharing',
295
-			]);
296
-			$failure = true;
297
-		}
298
-
299
-		if($failure) {
300
-			$this->removeShareFromTableById($shareId);
301
-			$message_t = $this->l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate.',
302
-				[$share->getNode()->getName(), $share->getSharedWith()]);
303
-			throw new \Exception($message_t);
304
-		}
305
-
306
-		return $shareId;
307
-
308
-	}
309
-
310
-	/**
311
-	 * @param string $shareWith
312
-	 * @param IShare $share
313
-	 * @param string $shareId internal share Id
314
-	 * @return array
315
-	 * @throws \Exception
316
-	 */
317
-	protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
318
-
319
-		$remoteShare = $this->getShareFromExternalShareTable($share);
320
-		$token = $remoteShare['share_token'];
321
-		$remoteId = $remoteShare['remote_id'];
322
-		$remote = $remoteShare['remote'];
323
-
324
-		list($token, $remoteId) = $this->notifications->requestReShare(
325
-			$token,
326
-			$remoteId,
327
-			$shareId,
328
-			$remote,
329
-			$shareWith,
330
-			$share->getPermissions(),
331
-			$share->getNode()->getName()
332
-		);
333
-
334
-		return [$token, $remoteId];
335
-	}
336
-
337
-	/**
338
-	 * get federated share from the share_external table but exclude mounted link shares
339
-	 *
340
-	 * @param IShare $share
341
-	 * @return array
342
-	 * @throws ShareNotFound
343
-	 */
344
-	protected function getShareFromExternalShareTable(IShare $share) {
345
-		$query = $this->dbConnection->getQueryBuilder();
346
-		$query->select('*')->from($this->externalShareTable)
347
-			->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
348
-			->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
349
-		$result = $query->execute()->fetchAll();
350
-
351
-		if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
352
-			return $result[0];
353
-		}
354
-
355
-		throw new ShareNotFound('share not found in share_external table');
356
-	}
357
-
358
-	/**
359
-	 * add share to the database and return the ID
360
-	 *
361
-	 * @param int $itemSource
362
-	 * @param string $itemType
363
-	 * @param string $shareWith
364
-	 * @param string $sharedBy
365
-	 * @param string $uidOwner
366
-	 * @param int $permissions
367
-	 * @param string $token
368
-	 * @param int $shareType
369
-	 * @return int
370
-	 */
371
-	private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
372
-		$qb = $this->dbConnection->getQueryBuilder();
373
-		$qb->insert('share')
374
-			->setValue('share_type', $qb->createNamedParameter($shareType))
375
-			->setValue('item_type', $qb->createNamedParameter($itemType))
376
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
377
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
378
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
379
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
380
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
381
-			->setValue('permissions', $qb->createNamedParameter($permissions))
382
-			->setValue('token', $qb->createNamedParameter($token))
383
-			->setValue('stime', $qb->createNamedParameter(time()));
384
-
385
-		/*
184
+        $alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
185
+        $alreadySharedGroup = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
186
+        if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
187
+            $message = 'Sharing %1$s failed, because this item is already shared with %2$s';
188
+            $message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with %2$s', array($share->getNode()->getName(), $shareWith));
189
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
190
+            throw new \Exception($message_t);
191
+        }
192
+
193
+
194
+        // don't allow federated shares if source and target server are the same
195
+        $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
196
+        $currentServer = $this->addressHandler->generateRemoteURL();
197
+        $currentUser = $sharedBy;
198
+        if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
199
+            $message = 'Not allowed to create a federated share with the same user.';
200
+            $message_t = $this->l->t('Not allowed to create a federated share with the same user');
201
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
202
+            throw new \Exception($message_t);
203
+        }
204
+
205
+
206
+        $share->setSharedWith($cloudId->getId());
207
+
208
+        try {
209
+            $remoteShare = $this->getShareFromExternalShareTable($share);
210
+        } catch (ShareNotFound $e) {
211
+            $remoteShare = null;
212
+        }
213
+
214
+        if ($remoteShare) {
215
+            try {
216
+                $ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
217
+                $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
218
+                $share->setId($shareId);
219
+                list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
220
+                // remote share was create successfully if we get a valid token as return
221
+                $send = is_string($token) && $token !== '';
222
+            } catch (\Exception $e) {
223
+                // fall back to old re-share behavior if the remote server
224
+                // doesn't support flat re-shares (was introduced with Nextcloud 9.1)
225
+                $this->removeShareFromTable($share);
226
+                $shareId = $this->createFederatedShare($share);
227
+            }
228
+            if ($send) {
229
+                $this->updateSuccessfulReshare($shareId, $token);
230
+                $this->storeRemoteId($shareId, $remoteId);
231
+            } else {
232
+                $this->removeShareFromTable($share);
233
+                $message_t = $this->l->t('File is already shared with %s', [$shareWith]);
234
+                throw new \Exception($message_t);
235
+            }
236
+
237
+        } else {
238
+            $shareId = $this->createFederatedShare($share);
239
+        }
240
+
241
+        $data = $this->getRawShare($shareId);
242
+        return $this->createShareObject($data);
243
+    }
244
+
245
+    /**
246
+     * create federated share and inform the recipient
247
+     *
248
+     * @param IShare $share
249
+     * @return int
250
+     * @throws ShareNotFound
251
+     * @throws \Exception
252
+     */
253
+    protected function createFederatedShare(IShare $share) {
254
+        $token = $this->tokenHandler->generateToken();
255
+        $shareId = $this->addShareToDB(
256
+            $share->getNodeId(),
257
+            $share->getNodeType(),
258
+            $share->getSharedWith(),
259
+            $share->getSharedBy(),
260
+            $share->getShareOwner(),
261
+            $share->getPermissions(),
262
+            $token,
263
+            $share->getShareType()
264
+        );
265
+
266
+        $failure = false;
267
+
268
+        try {
269
+            $sharedByFederatedId = $share->getSharedBy();
270
+            if ($this->userManager->userExists($sharedByFederatedId)) {
271
+                $cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
272
+                $sharedByFederatedId = $cloudId->getId();
273
+            }
274
+            $ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
275
+            $send = $this->notifications->sendRemoteShare(
276
+                $token,
277
+                $share->getSharedWith(),
278
+                $share->getNode()->getName(),
279
+                $shareId,
280
+                $share->getShareOwner(),
281
+                $ownerCloudId->getId(),
282
+                $share->getSharedBy(),
283
+                $sharedByFederatedId,
284
+                $share->getShareType()
285
+            );
286
+
287
+            if ($send === false) {
288
+                $failure = true;
289
+            }
290
+        } catch (\Exception $e) {
291
+            $this->logger->logException($e, [
292
+                'message' => 'Failed to notify remote server of federated share, removing share.',
293
+                'level' => ILogger::ERROR,
294
+                'app' => 'federatedfilesharing',
295
+            ]);
296
+            $failure = true;
297
+        }
298
+
299
+        if($failure) {
300
+            $this->removeShareFromTableById($shareId);
301
+            $message_t = $this->l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate.',
302
+                [$share->getNode()->getName(), $share->getSharedWith()]);
303
+            throw new \Exception($message_t);
304
+        }
305
+
306
+        return $shareId;
307
+
308
+    }
309
+
310
+    /**
311
+     * @param string $shareWith
312
+     * @param IShare $share
313
+     * @param string $shareId internal share Id
314
+     * @return array
315
+     * @throws \Exception
316
+     */
317
+    protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
318
+
319
+        $remoteShare = $this->getShareFromExternalShareTable($share);
320
+        $token = $remoteShare['share_token'];
321
+        $remoteId = $remoteShare['remote_id'];
322
+        $remote = $remoteShare['remote'];
323
+
324
+        list($token, $remoteId) = $this->notifications->requestReShare(
325
+            $token,
326
+            $remoteId,
327
+            $shareId,
328
+            $remote,
329
+            $shareWith,
330
+            $share->getPermissions(),
331
+            $share->getNode()->getName()
332
+        );
333
+
334
+        return [$token, $remoteId];
335
+    }
336
+
337
+    /**
338
+     * get federated share from the share_external table but exclude mounted link shares
339
+     *
340
+     * @param IShare $share
341
+     * @return array
342
+     * @throws ShareNotFound
343
+     */
344
+    protected function getShareFromExternalShareTable(IShare $share) {
345
+        $query = $this->dbConnection->getQueryBuilder();
346
+        $query->select('*')->from($this->externalShareTable)
347
+            ->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
348
+            ->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
349
+        $result = $query->execute()->fetchAll();
350
+
351
+        if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
352
+            return $result[0];
353
+        }
354
+
355
+        throw new ShareNotFound('share not found in share_external table');
356
+    }
357
+
358
+    /**
359
+     * add share to the database and return the ID
360
+     *
361
+     * @param int $itemSource
362
+     * @param string $itemType
363
+     * @param string $shareWith
364
+     * @param string $sharedBy
365
+     * @param string $uidOwner
366
+     * @param int $permissions
367
+     * @param string $token
368
+     * @param int $shareType
369
+     * @return int
370
+     */
371
+    private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
372
+        $qb = $this->dbConnection->getQueryBuilder();
373
+        $qb->insert('share')
374
+            ->setValue('share_type', $qb->createNamedParameter($shareType))
375
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
376
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
377
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
378
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
379
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
380
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
381
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
382
+            ->setValue('token', $qb->createNamedParameter($token))
383
+            ->setValue('stime', $qb->createNamedParameter(time()));
384
+
385
+        /*
386 386
 		 * Added to fix https://github.com/owncloud/core/issues/22215
387 387
 		 * Can be removed once we get rid of ajax/share.php
388 388
 		 */
389
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
390
-
391
-		$qb->execute();
392
-		$id = $qb->getLastInsertId();
393
-
394
-		return (int)$id;
395
-	}
396
-
397
-	/**
398
-	 * Update a share
399
-	 *
400
-	 * @param IShare $share
401
-	 * @return IShare The share object
402
-	 */
403
-	public function update(IShare $share) {
404
-		/*
389
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
390
+
391
+        $qb->execute();
392
+        $id = $qb->getLastInsertId();
393
+
394
+        return (int)$id;
395
+    }
396
+
397
+    /**
398
+     * Update a share
399
+     *
400
+     * @param IShare $share
401
+     * @return IShare The share object
402
+     */
403
+    public function update(IShare $share) {
404
+        /*
405 405
 		 * We allow updating the permissions of federated shares
406 406
 		 */
407
-		$qb = $this->dbConnection->getQueryBuilder();
408
-			$qb->update('share')
409
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
410
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
411
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
412
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
413
-				->execute();
414
-
415
-		// send the updated permission to the owner/initiator, if they are not the same
416
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
417
-			$this->sendPermissionUpdate($share);
418
-		}
419
-
420
-		return $share;
421
-	}
422
-
423
-	/**
424
-	 * send the updated permission to the owner/initiator, if they are not the same
425
-	 *
426
-	 * @param IShare $share
427
-	 * @throws ShareNotFound
428
-	 * @throws \OC\HintException
429
-	 */
430
-	protected function sendPermissionUpdate(IShare $share) {
431
-		$remoteId = $this->getRemoteId($share);
432
-		// if the local user is the owner we send the permission change to the initiator
433
-		if ($this->userManager->userExists($share->getShareOwner())) {
434
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
435
-		} else { // ... if not we send the permission change to the owner
436
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
437
-		}
438
-		$this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
439
-	}
440
-
441
-
442
-	/**
443
-	 * update successful reShare with the correct token
444
-	 *
445
-	 * @param int $shareId
446
-	 * @param string $token
447
-	 */
448
-	protected function updateSuccessfulReShare($shareId, $token) {
449
-		$query = $this->dbConnection->getQueryBuilder();
450
-		$query->update('share')
451
-			->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
452
-			->set('token', $query->createNamedParameter($token))
453
-			->execute();
454
-	}
455
-
456
-	/**
457
-	 * store remote ID in federated reShare table
458
-	 *
459
-	 * @param $shareId
460
-	 * @param $remoteId
461
-	 */
462
-	public function storeRemoteId($shareId, $remoteId) {
463
-		$query = $this->dbConnection->getQueryBuilder();
464
-		$query->insert('federated_reshares')
465
-			->values(
466
-				[
467
-					'share_id' =>  $query->createNamedParameter($shareId),
468
-					'remote_id' => $query->createNamedParameter($remoteId),
469
-				]
470
-			);
471
-		$query->execute();
472
-	}
473
-
474
-	/**
475
-	 * get share ID on remote server for federated re-shares
476
-	 *
477
-	 * @param IShare $share
478
-	 * @return int
479
-	 * @throws ShareNotFound
480
-	 */
481
-	public function getRemoteId(IShare $share) {
482
-		$query = $this->dbConnection->getQueryBuilder();
483
-		$query->select('remote_id')->from('federated_reshares')
484
-			->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
485
-		$data = $query->execute()->fetch();
486
-
487
-		if (!is_array($data) || !isset($data['remote_id'])) {
488
-			throw new ShareNotFound();
489
-		}
490
-
491
-		return (int)$data['remote_id'];
492
-	}
493
-
494
-	/**
495
-	 * @inheritdoc
496
-	 */
497
-	public function move(IShare $share, $recipient) {
498
-		/*
407
+        $qb = $this->dbConnection->getQueryBuilder();
408
+            $qb->update('share')
409
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
410
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
411
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
412
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
413
+                ->execute();
414
+
415
+        // send the updated permission to the owner/initiator, if they are not the same
416
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
417
+            $this->sendPermissionUpdate($share);
418
+        }
419
+
420
+        return $share;
421
+    }
422
+
423
+    /**
424
+     * send the updated permission to the owner/initiator, if they are not the same
425
+     *
426
+     * @param IShare $share
427
+     * @throws ShareNotFound
428
+     * @throws \OC\HintException
429
+     */
430
+    protected function sendPermissionUpdate(IShare $share) {
431
+        $remoteId = $this->getRemoteId($share);
432
+        // if the local user is the owner we send the permission change to the initiator
433
+        if ($this->userManager->userExists($share->getShareOwner())) {
434
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
435
+        } else { // ... if not we send the permission change to the owner
436
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
437
+        }
438
+        $this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
439
+    }
440
+
441
+
442
+    /**
443
+     * update successful reShare with the correct token
444
+     *
445
+     * @param int $shareId
446
+     * @param string $token
447
+     */
448
+    protected function updateSuccessfulReShare($shareId, $token) {
449
+        $query = $this->dbConnection->getQueryBuilder();
450
+        $query->update('share')
451
+            ->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
452
+            ->set('token', $query->createNamedParameter($token))
453
+            ->execute();
454
+    }
455
+
456
+    /**
457
+     * store remote ID in federated reShare table
458
+     *
459
+     * @param $shareId
460
+     * @param $remoteId
461
+     */
462
+    public function storeRemoteId($shareId, $remoteId) {
463
+        $query = $this->dbConnection->getQueryBuilder();
464
+        $query->insert('federated_reshares')
465
+            ->values(
466
+                [
467
+                    'share_id' =>  $query->createNamedParameter($shareId),
468
+                    'remote_id' => $query->createNamedParameter($remoteId),
469
+                ]
470
+            );
471
+        $query->execute();
472
+    }
473
+
474
+    /**
475
+     * get share ID on remote server for federated re-shares
476
+     *
477
+     * @param IShare $share
478
+     * @return int
479
+     * @throws ShareNotFound
480
+     */
481
+    public function getRemoteId(IShare $share) {
482
+        $query = $this->dbConnection->getQueryBuilder();
483
+        $query->select('remote_id')->from('federated_reshares')
484
+            ->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
485
+        $data = $query->execute()->fetch();
486
+
487
+        if (!is_array($data) || !isset($data['remote_id'])) {
488
+            throw new ShareNotFound();
489
+        }
490
+
491
+        return (int)$data['remote_id'];
492
+    }
493
+
494
+    /**
495
+     * @inheritdoc
496
+     */
497
+    public function move(IShare $share, $recipient) {
498
+        /*
499 499
 		 * This function does nothing yet as it is just for outgoing
500 500
 		 * federated shares.
501 501
 		 */
502
-		return $share;
503
-	}
504
-
505
-	/**
506
-	 * Get all children of this share
507
-	 *
508
-	 * @param IShare $parent
509
-	 * @return IShare[]
510
-	 */
511
-	public function getChildren(IShare $parent) {
512
-		$children = [];
513
-
514
-		$qb = $this->dbConnection->getQueryBuilder();
515
-		$qb->select('*')
516
-			->from('share')
517
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
518
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
519
-			->orderBy('id');
520
-
521
-		$cursor = $qb->execute();
522
-		while($data = $cursor->fetch()) {
523
-			$children[] = $this->createShareObject($data);
524
-		}
525
-		$cursor->closeCursor();
526
-
527
-		return $children;
528
-	}
529
-
530
-	/**
531
-	 * Delete a share (owner unShares the file)
532
-	 *
533
-	 * @param IShare $share
534
-	 * @throws ShareNotFound
535
-	 * @throws \OC\HintException
536
-	 */
537
-	public function delete(IShare $share) {
538
-
539
-		list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
540
-
541
-		// if the local user is the owner we can send the unShare request directly...
542
-		if ($this->userManager->userExists($share->getShareOwner())) {
543
-			$this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
544
-			$this->revokeShare($share, true);
545
-		} else { // ... if not we need to correct ID for the unShare request
546
-			$remoteId = $this->getRemoteId($share);
547
-			$this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
548
-			$this->revokeShare($share, false);
549
-		}
550
-
551
-		// only remove the share when all messages are send to not lose information
552
-		// about the share to early
553
-		$this->removeShareFromTable($share);
554
-	}
555
-
556
-	/**
557
-	 * in case of a re-share we need to send the other use (initiator or owner)
558
-	 * a message that the file was unshared
559
-	 *
560
-	 * @param IShare $share
561
-	 * @param bool $isOwner the user can either be the owner or the user who re-sahred it
562
-	 * @throws ShareNotFound
563
-	 * @throws \OC\HintException
564
-	 */
565
-	protected function revokeShare($share, $isOwner) {
566
-		// also send a unShare request to the initiator, if this is a different user than the owner
567
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
568
-			if ($isOwner) {
569
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
570
-			} else {
571
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
572
-			}
573
-			$remoteId = $this->getRemoteId($share);
574
-			$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
575
-		}
576
-	}
577
-
578
-	/**
579
-	 * remove share from table
580
-	 *
581
-	 * @param IShare $share
582
-	 */
583
-	public function removeShareFromTable(IShare $share) {
584
-		$this->removeShareFromTableById($share->getId());
585
-	}
586
-
587
-	/**
588
-	 * remove share from table
589
-	 *
590
-	 * @param string $shareId
591
-	 */
592
-	private function removeShareFromTableById($shareId) {
593
-		$qb = $this->dbConnection->getQueryBuilder();
594
-		$qb->delete('share')
595
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
596
-		$qb->execute();
597
-
598
-		$qb->delete('federated_reshares')
599
-			->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
600
-		$qb->execute();
601
-	}
602
-
603
-	/**
604
-	 * @inheritdoc
605
-	 */
606
-	public function deleteFromSelf(IShare $share, $recipient) {
607
-		// nothing to do here. Technically deleteFromSelf in the context of federated
608
-		// shares is a umount of a external storage. This is handled here
609
-		// apps/files_sharing/lib/external/manager.php
610
-		// TODO move this code over to this app
611
-	}
612
-
613
-	public function restore(IShare $share, string $recipient): IShare {
614
-		throw new GenericShareException('not implemented');
615
-	}
616
-
617
-
618
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
619
-		$qb = $this->dbConnection->getQueryBuilder();
620
-		$qb->select('*')
621
-			->from('share', 's')
622
-			->andWhere($qb->expr()->orX(
623
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
624
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
625
-			))
626
-			->andWhere(
627
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))
628
-			);
629
-
630
-		/**
631
-		 * Reshares for this user are shares where they are the owner.
632
-		 */
633
-		if ($reshares === false) {
634
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
635
-		} else {
636
-			$qb->andWhere(
637
-				$qb->expr()->orX(
638
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
639
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
640
-				)
641
-			);
642
-		}
643
-
644
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
645
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
646
-
647
-		$qb->orderBy('id');
648
-
649
-		$cursor = $qb->execute();
650
-		$shares = [];
651
-		while ($data = $cursor->fetch()) {
652
-			$shares[$data['fileid']][] = $this->createShareObject($data);
653
-		}
654
-		$cursor->closeCursor();
655
-
656
-		return $shares;
657
-	}
658
-
659
-	/**
660
-	 * @inheritdoc
661
-	 */
662
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
663
-		$qb = $this->dbConnection->getQueryBuilder();
664
-		$qb->select('*')
665
-			->from('share');
666
-
667
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
668
-
669
-		/**
670
-		 * Reshares for this user are shares where they are the owner.
671
-		 */
672
-		if ($reshares === false) {
673
-			//Special case for old shares created via the web UI
674
-			$or1 = $qb->expr()->andX(
675
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
676
-				$qb->expr()->isNull('uid_initiator')
677
-			);
678
-
679
-			$qb->andWhere(
680
-				$qb->expr()->orX(
681
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
682
-					$or1
683
-				)
684
-			);
685
-		} else {
686
-			$qb->andWhere(
687
-				$qb->expr()->orX(
688
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
689
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
690
-				)
691
-			);
692
-		}
693
-
694
-		if ($node !== null) {
695
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
696
-		}
697
-
698
-		if ($limit !== -1) {
699
-			$qb->setMaxResults($limit);
700
-		}
701
-
702
-		$qb->setFirstResult($offset);
703
-		$qb->orderBy('id');
704
-
705
-		$cursor = $qb->execute();
706
-		$shares = [];
707
-		while($data = $cursor->fetch()) {
708
-			$shares[] = $this->createShareObject($data);
709
-		}
710
-		$cursor->closeCursor();
711
-
712
-		return $shares;
713
-	}
714
-
715
-	/**
716
-	 * @inheritdoc
717
-	 */
718
-	public function getShareById($id, $recipientId = null) {
719
-		$qb = $this->dbConnection->getQueryBuilder();
720
-
721
-		$qb->select('*')
722
-			->from('share')
723
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
724
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
725
-
726
-		$cursor = $qb->execute();
727
-		$data = $cursor->fetch();
728
-		$cursor->closeCursor();
729
-
730
-		if ($data === false) {
731
-			throw new ShareNotFound('Can not find share with ID: ' . $id);
732
-		}
733
-
734
-		try {
735
-			$share = $this->createShareObject($data);
736
-		} catch (InvalidShare $e) {
737
-			throw new ShareNotFound();
738
-		}
739
-
740
-		return $share;
741
-	}
742
-
743
-	/**
744
-	 * Get shares for a given path
745
-	 *
746
-	 * @param \OCP\Files\Node $path
747
-	 * @return IShare[]
748
-	 */
749
-	public function getSharesByPath(Node $path) {
750
-		$qb = $this->dbConnection->getQueryBuilder();
751
-
752
-		// get federated user shares
753
-		$cursor = $qb->select('*')
754
-			->from('share')
755
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
756
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
757
-			->execute();
758
-
759
-		$shares = [];
760
-		while($data = $cursor->fetch()) {
761
-			$shares[] = $this->createShareObject($data);
762
-		}
763
-		$cursor->closeCursor();
764
-
765
-		return $shares;
766
-	}
767
-
768
-	/**
769
-	 * @inheritdoc
770
-	 */
771
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
772
-		/** @var IShare[] $shares */
773
-		$shares = [];
774
-
775
-		//Get shares directly with this user
776
-		$qb = $this->dbConnection->getQueryBuilder();
777
-		$qb->select('*')
778
-			->from('share');
779
-
780
-		// Order by id
781
-		$qb->orderBy('id');
782
-
783
-		// Set limit and offset
784
-		if ($limit !== -1) {
785
-			$qb->setMaxResults($limit);
786
-		}
787
-		$qb->setFirstResult($offset);
788
-
789
-		$qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
790
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
791
-
792
-		// Filter by node if provided
793
-		if ($node !== null) {
794
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
795
-		}
796
-
797
-		$cursor = $qb->execute();
798
-
799
-		while($data = $cursor->fetch()) {
800
-			$shares[] = $this->createShareObject($data);
801
-		}
802
-		$cursor->closeCursor();
803
-
804
-
805
-		return $shares;
806
-	}
807
-
808
-	/**
809
-	 * Get a share by token
810
-	 *
811
-	 * @param string $token
812
-	 * @return IShare
813
-	 * @throws ShareNotFound
814
-	 */
815
-	public function getShareByToken($token) {
816
-		$qb = $this->dbConnection->getQueryBuilder();
817
-
818
-		$cursor = $qb->select('*')
819
-			->from('share')
820
-			->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
821
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
822
-			->execute();
823
-
824
-		$data = $cursor->fetch();
825
-
826
-		if ($data === false) {
827
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
828
-		}
829
-
830
-		try {
831
-			$share = $this->createShareObject($data);
832
-		} catch (InvalidShare $e) {
833
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
834
-		}
835
-
836
-		return $share;
837
-	}
838
-
839
-	/**
840
-	 * get database row of a give share
841
-	 *
842
-	 * @param $id
843
-	 * @return array
844
-	 * @throws ShareNotFound
845
-	 */
846
-	private function getRawShare($id) {
847
-
848
-		// Now fetch the inserted share and create a complete share object
849
-		$qb = $this->dbConnection->getQueryBuilder();
850
-		$qb->select('*')
851
-			->from('share')
852
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
853
-
854
-		$cursor = $qb->execute();
855
-		$data = $cursor->fetch();
856
-		$cursor->closeCursor();
857
-
858
-		if ($data === false) {
859
-			throw new ShareNotFound;
860
-		}
861
-
862
-		return $data;
863
-	}
864
-
865
-	/**
866
-	 * Create a share object from an database row
867
-	 *
868
-	 * @param array $data
869
-	 * @return IShare
870
-	 * @throws InvalidShare
871
-	 * @throws ShareNotFound
872
-	 */
873
-	private function createShareObject($data) {
874
-
875
-		$share = new Share($this->rootFolder, $this->userManager);
876
-		$share->setId((int)$data['id'])
877
-			->setShareType((int)$data['share_type'])
878
-			->setPermissions((int)$data['permissions'])
879
-			->setTarget($data['file_target'])
880
-			->setMailSend((bool)$data['mail_send'])
881
-			->setToken($data['token']);
882
-
883
-		$shareTime = new \DateTime();
884
-		$shareTime->setTimestamp((int)$data['stime']);
885
-		$share->setShareTime($shareTime);
886
-		$share->setSharedWith($data['share_with']);
887
-
888
-		if ($data['uid_initiator'] !== null) {
889
-			$share->setShareOwner($data['uid_owner']);
890
-			$share->setSharedBy($data['uid_initiator']);
891
-		} else {
892
-			//OLD SHARE
893
-			$share->setSharedBy($data['uid_owner']);
894
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
895
-
896
-			$owner = $path->getOwner();
897
-			$share->setShareOwner($owner->getUID());
898
-		}
899
-
900
-		$share->setNodeId((int)$data['file_source']);
901
-		$share->setNodeType($data['item_type']);
902
-
903
-		$share->setProviderId($this->identifier());
904
-
905
-		return $share;
906
-	}
907
-
908
-	/**
909
-	 * Get the node with file $id for $user
910
-	 *
911
-	 * @param string $userId
912
-	 * @param int $id
913
-	 * @return \OCP\Files\File|\OCP\Files\Folder
914
-	 * @throws InvalidShare
915
-	 */
916
-	private function getNode($userId, $id) {
917
-		try {
918
-			$userFolder = $this->rootFolder->getUserFolder($userId);
919
-		} catch (NotFoundException $e) {
920
-			throw new InvalidShare();
921
-		}
922
-
923
-		$nodes = $userFolder->getById($id);
924
-
925
-		if (empty($nodes)) {
926
-			throw new InvalidShare();
927
-		}
928
-
929
-		return $nodes[0];
930
-	}
931
-
932
-	/**
933
-	 * A user is deleted from the system
934
-	 * So clean up the relevant shares.
935
-	 *
936
-	 * @param string $uid
937
-	 * @param int $shareType
938
-	 */
939
-	public function userDeleted($uid, $shareType) {
940
-		//TODO: probabaly a good idea to send unshare info to remote servers
941
-
942
-		$qb = $this->dbConnection->getQueryBuilder();
943
-
944
-		$qb->delete('share')
945
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
946
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
947
-			->execute();
948
-	}
949
-
950
-	/**
951
-	 * This provider does not handle groups
952
-	 *
953
-	 * @param string $gid
954
-	 */
955
-	public function groupDeleted($gid) {
956
-		// We don't handle groups here
957
-	}
958
-
959
-	/**
960
-	 * This provider does not handle groups
961
-	 *
962
-	 * @param string $uid
963
-	 * @param string $gid
964
-	 */
965
-	public function userDeletedFromGroup($uid, $gid) {
966
-		// We don't handle groups here
967
-	}
968
-
969
-	/**
970
-	 * check if users from other Nextcloud instances are allowed to mount public links share by this instance
971
-	 *
972
-	 * @return bool
973
-	 */
974
-	public function isOutgoingServer2serverShareEnabled() {
975
-		if ($this->gsConfig->onlyInternalFederation()) {
976
-			return false;
977
-		}
978
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
979
-		return ($result === 'yes');
980
-	}
981
-
982
-	/**
983
-	 * check if users are allowed to mount public links from other Nextclouds
984
-	 *
985
-	 * @return bool
986
-	 */
987
-	public function isIncomingServer2serverShareEnabled() {
988
-		if ($this->gsConfig->onlyInternalFederation()) {
989
-			return false;
990
-		}
991
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
992
-		return ($result === 'yes');
993
-	}
994
-
995
-
996
-	/**
997
-	 * check if users from other Nextcloud instances are allowed to send federated group shares
998
-	 *
999
-	 * @return bool
1000
-	 */
1001
-	public function isOutgoingServer2serverGroupShareEnabled() {
1002
-		if ($this->gsConfig->onlyInternalFederation()) {
1003
-			return false;
1004
-		}
1005
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
1006
-		return ($result === 'yes');
1007
-	}
1008
-
1009
-	/**
1010
-	 * check if users are allowed to receive federated group shares
1011
-	 *
1012
-	 * @return bool
1013
-	 */
1014
-	public function isIncomingServer2serverGroupShareEnabled() {
1015
-		if ($this->gsConfig->onlyInternalFederation()) {
1016
-			return false;
1017
-		}
1018
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
1019
-		return ($result === 'yes');
1020
-	}
1021
-
1022
-	/**
1023
-	 * check if federated group sharing is supported, therefore the OCM API need to be enabled
1024
-	 *
1025
-	 * @return bool
1026
-	 */
1027
-	public function isFederatedGroupSharingSupported() {
1028
-		return $this->cloudFederationProviderManager->isReady();
1029
-	}
1030
-
1031
-	/**
1032
-	 * Check if querying sharees on the lookup server is enabled
1033
-	 *
1034
-	 * @return bool
1035
-	 */
1036
-	public function isLookupServerQueriesEnabled() {
1037
-		// in a global scale setup we should always query the lookup server
1038
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1039
-			return true;
1040
-		}
1041
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no');
1042
-		return ($result === 'yes');
1043
-	}
1044
-
1045
-
1046
-	/**
1047
-	 * Check if it is allowed to publish user specific data to the lookup server
1048
-	 *
1049
-	 * @return bool
1050
-	 */
1051
-	public function isLookupServerUploadEnabled() {
1052
-		// in a global scale setup the admin is responsible to keep the lookup server up-to-date
1053
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1054
-			return false;
1055
-		}
1056
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1057
-		return ($result === 'yes');
1058
-	}
1059
-
1060
-	/**
1061
-	 * @inheritdoc
1062
-	 */
1063
-	public function getAccessList($nodes, $currentAccess) {
1064
-		$ids = [];
1065
-		foreach ($nodes as $node) {
1066
-			$ids[] = $node->getId();
1067
-		}
1068
-
1069
-		$qb = $this->dbConnection->getQueryBuilder();
1070
-		$qb->select('share_with', 'token', 'file_source')
1071
-			->from('share')
1072
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
1073
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1074
-			->andWhere($qb->expr()->orX(
1075
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1076
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1077
-			));
1078
-		$cursor = $qb->execute();
1079
-
1080
-		if ($currentAccess === false) {
1081
-			$remote = $cursor->fetch() !== false;
1082
-			$cursor->closeCursor();
1083
-
1084
-			return ['remote' => $remote];
1085
-		}
1086
-
1087
-		$remote = [];
1088
-		while ($row = $cursor->fetch()) {
1089
-			$remote[$row['share_with']] = [
1090
-				'node_id' => $row['file_source'],
1091
-				'token' => $row['token'],
1092
-			];
1093
-		}
1094
-		$cursor->closeCursor();
1095
-
1096
-		return ['remote' => $remote];
1097
-	}
502
+        return $share;
503
+    }
504
+
505
+    /**
506
+     * Get all children of this share
507
+     *
508
+     * @param IShare $parent
509
+     * @return IShare[]
510
+     */
511
+    public function getChildren(IShare $parent) {
512
+        $children = [];
513
+
514
+        $qb = $this->dbConnection->getQueryBuilder();
515
+        $qb->select('*')
516
+            ->from('share')
517
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
518
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
519
+            ->orderBy('id');
520
+
521
+        $cursor = $qb->execute();
522
+        while($data = $cursor->fetch()) {
523
+            $children[] = $this->createShareObject($data);
524
+        }
525
+        $cursor->closeCursor();
526
+
527
+        return $children;
528
+    }
529
+
530
+    /**
531
+     * Delete a share (owner unShares the file)
532
+     *
533
+     * @param IShare $share
534
+     * @throws ShareNotFound
535
+     * @throws \OC\HintException
536
+     */
537
+    public function delete(IShare $share) {
538
+
539
+        list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
540
+
541
+        // if the local user is the owner we can send the unShare request directly...
542
+        if ($this->userManager->userExists($share->getShareOwner())) {
543
+            $this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
544
+            $this->revokeShare($share, true);
545
+        } else { // ... if not we need to correct ID for the unShare request
546
+            $remoteId = $this->getRemoteId($share);
547
+            $this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
548
+            $this->revokeShare($share, false);
549
+        }
550
+
551
+        // only remove the share when all messages are send to not lose information
552
+        // about the share to early
553
+        $this->removeShareFromTable($share);
554
+    }
555
+
556
+    /**
557
+     * in case of a re-share we need to send the other use (initiator or owner)
558
+     * a message that the file was unshared
559
+     *
560
+     * @param IShare $share
561
+     * @param bool $isOwner the user can either be the owner or the user who re-sahred it
562
+     * @throws ShareNotFound
563
+     * @throws \OC\HintException
564
+     */
565
+    protected function revokeShare($share, $isOwner) {
566
+        // also send a unShare request to the initiator, if this is a different user than the owner
567
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
568
+            if ($isOwner) {
569
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
570
+            } else {
571
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
572
+            }
573
+            $remoteId = $this->getRemoteId($share);
574
+            $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
575
+        }
576
+    }
577
+
578
+    /**
579
+     * remove share from table
580
+     *
581
+     * @param IShare $share
582
+     */
583
+    public function removeShareFromTable(IShare $share) {
584
+        $this->removeShareFromTableById($share->getId());
585
+    }
586
+
587
+    /**
588
+     * remove share from table
589
+     *
590
+     * @param string $shareId
591
+     */
592
+    private function removeShareFromTableById($shareId) {
593
+        $qb = $this->dbConnection->getQueryBuilder();
594
+        $qb->delete('share')
595
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
596
+        $qb->execute();
597
+
598
+        $qb->delete('federated_reshares')
599
+            ->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
600
+        $qb->execute();
601
+    }
602
+
603
+    /**
604
+     * @inheritdoc
605
+     */
606
+    public function deleteFromSelf(IShare $share, $recipient) {
607
+        // nothing to do here. Technically deleteFromSelf in the context of federated
608
+        // shares is a umount of a external storage. This is handled here
609
+        // apps/files_sharing/lib/external/manager.php
610
+        // TODO move this code over to this app
611
+    }
612
+
613
+    public function restore(IShare $share, string $recipient): IShare {
614
+        throw new GenericShareException('not implemented');
615
+    }
616
+
617
+
618
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
619
+        $qb = $this->dbConnection->getQueryBuilder();
620
+        $qb->select('*')
621
+            ->from('share', 's')
622
+            ->andWhere($qb->expr()->orX(
623
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
624
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
625
+            ))
626
+            ->andWhere(
627
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))
628
+            );
629
+
630
+        /**
631
+         * Reshares for this user are shares where they are the owner.
632
+         */
633
+        if ($reshares === false) {
634
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
635
+        } else {
636
+            $qb->andWhere(
637
+                $qb->expr()->orX(
638
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
639
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
640
+                )
641
+            );
642
+        }
643
+
644
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
645
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
646
+
647
+        $qb->orderBy('id');
648
+
649
+        $cursor = $qb->execute();
650
+        $shares = [];
651
+        while ($data = $cursor->fetch()) {
652
+            $shares[$data['fileid']][] = $this->createShareObject($data);
653
+        }
654
+        $cursor->closeCursor();
655
+
656
+        return $shares;
657
+    }
658
+
659
+    /**
660
+     * @inheritdoc
661
+     */
662
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
663
+        $qb = $this->dbConnection->getQueryBuilder();
664
+        $qb->select('*')
665
+            ->from('share');
666
+
667
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
668
+
669
+        /**
670
+         * Reshares for this user are shares where they are the owner.
671
+         */
672
+        if ($reshares === false) {
673
+            //Special case for old shares created via the web UI
674
+            $or1 = $qb->expr()->andX(
675
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
676
+                $qb->expr()->isNull('uid_initiator')
677
+            );
678
+
679
+            $qb->andWhere(
680
+                $qb->expr()->orX(
681
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
682
+                    $or1
683
+                )
684
+            );
685
+        } else {
686
+            $qb->andWhere(
687
+                $qb->expr()->orX(
688
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
689
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
690
+                )
691
+            );
692
+        }
693
+
694
+        if ($node !== null) {
695
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
696
+        }
697
+
698
+        if ($limit !== -1) {
699
+            $qb->setMaxResults($limit);
700
+        }
701
+
702
+        $qb->setFirstResult($offset);
703
+        $qb->orderBy('id');
704
+
705
+        $cursor = $qb->execute();
706
+        $shares = [];
707
+        while($data = $cursor->fetch()) {
708
+            $shares[] = $this->createShareObject($data);
709
+        }
710
+        $cursor->closeCursor();
711
+
712
+        return $shares;
713
+    }
714
+
715
+    /**
716
+     * @inheritdoc
717
+     */
718
+    public function getShareById($id, $recipientId = null) {
719
+        $qb = $this->dbConnection->getQueryBuilder();
720
+
721
+        $qb->select('*')
722
+            ->from('share')
723
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
724
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
725
+
726
+        $cursor = $qb->execute();
727
+        $data = $cursor->fetch();
728
+        $cursor->closeCursor();
729
+
730
+        if ($data === false) {
731
+            throw new ShareNotFound('Can not find share with ID: ' . $id);
732
+        }
733
+
734
+        try {
735
+            $share = $this->createShareObject($data);
736
+        } catch (InvalidShare $e) {
737
+            throw new ShareNotFound();
738
+        }
739
+
740
+        return $share;
741
+    }
742
+
743
+    /**
744
+     * Get shares for a given path
745
+     *
746
+     * @param \OCP\Files\Node $path
747
+     * @return IShare[]
748
+     */
749
+    public function getSharesByPath(Node $path) {
750
+        $qb = $this->dbConnection->getQueryBuilder();
751
+
752
+        // get federated user shares
753
+        $cursor = $qb->select('*')
754
+            ->from('share')
755
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
756
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
757
+            ->execute();
758
+
759
+        $shares = [];
760
+        while($data = $cursor->fetch()) {
761
+            $shares[] = $this->createShareObject($data);
762
+        }
763
+        $cursor->closeCursor();
764
+
765
+        return $shares;
766
+    }
767
+
768
+    /**
769
+     * @inheritdoc
770
+     */
771
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
772
+        /** @var IShare[] $shares */
773
+        $shares = [];
774
+
775
+        //Get shares directly with this user
776
+        $qb = $this->dbConnection->getQueryBuilder();
777
+        $qb->select('*')
778
+            ->from('share');
779
+
780
+        // Order by id
781
+        $qb->orderBy('id');
782
+
783
+        // Set limit and offset
784
+        if ($limit !== -1) {
785
+            $qb->setMaxResults($limit);
786
+        }
787
+        $qb->setFirstResult($offset);
788
+
789
+        $qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
790
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
791
+
792
+        // Filter by node if provided
793
+        if ($node !== null) {
794
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
795
+        }
796
+
797
+        $cursor = $qb->execute();
798
+
799
+        while($data = $cursor->fetch()) {
800
+            $shares[] = $this->createShareObject($data);
801
+        }
802
+        $cursor->closeCursor();
803
+
804
+
805
+        return $shares;
806
+    }
807
+
808
+    /**
809
+     * Get a share by token
810
+     *
811
+     * @param string $token
812
+     * @return IShare
813
+     * @throws ShareNotFound
814
+     */
815
+    public function getShareByToken($token) {
816
+        $qb = $this->dbConnection->getQueryBuilder();
817
+
818
+        $cursor = $qb->select('*')
819
+            ->from('share')
820
+            ->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
821
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
822
+            ->execute();
823
+
824
+        $data = $cursor->fetch();
825
+
826
+        if ($data === false) {
827
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
828
+        }
829
+
830
+        try {
831
+            $share = $this->createShareObject($data);
832
+        } catch (InvalidShare $e) {
833
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
834
+        }
835
+
836
+        return $share;
837
+    }
838
+
839
+    /**
840
+     * get database row of a give share
841
+     *
842
+     * @param $id
843
+     * @return array
844
+     * @throws ShareNotFound
845
+     */
846
+    private function getRawShare($id) {
847
+
848
+        // Now fetch the inserted share and create a complete share object
849
+        $qb = $this->dbConnection->getQueryBuilder();
850
+        $qb->select('*')
851
+            ->from('share')
852
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
853
+
854
+        $cursor = $qb->execute();
855
+        $data = $cursor->fetch();
856
+        $cursor->closeCursor();
857
+
858
+        if ($data === false) {
859
+            throw new ShareNotFound;
860
+        }
861
+
862
+        return $data;
863
+    }
864
+
865
+    /**
866
+     * Create a share object from an database row
867
+     *
868
+     * @param array $data
869
+     * @return IShare
870
+     * @throws InvalidShare
871
+     * @throws ShareNotFound
872
+     */
873
+    private function createShareObject($data) {
874
+
875
+        $share = new Share($this->rootFolder, $this->userManager);
876
+        $share->setId((int)$data['id'])
877
+            ->setShareType((int)$data['share_type'])
878
+            ->setPermissions((int)$data['permissions'])
879
+            ->setTarget($data['file_target'])
880
+            ->setMailSend((bool)$data['mail_send'])
881
+            ->setToken($data['token']);
882
+
883
+        $shareTime = new \DateTime();
884
+        $shareTime->setTimestamp((int)$data['stime']);
885
+        $share->setShareTime($shareTime);
886
+        $share->setSharedWith($data['share_with']);
887
+
888
+        if ($data['uid_initiator'] !== null) {
889
+            $share->setShareOwner($data['uid_owner']);
890
+            $share->setSharedBy($data['uid_initiator']);
891
+        } else {
892
+            //OLD SHARE
893
+            $share->setSharedBy($data['uid_owner']);
894
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
895
+
896
+            $owner = $path->getOwner();
897
+            $share->setShareOwner($owner->getUID());
898
+        }
899
+
900
+        $share->setNodeId((int)$data['file_source']);
901
+        $share->setNodeType($data['item_type']);
902
+
903
+        $share->setProviderId($this->identifier());
904
+
905
+        return $share;
906
+    }
907
+
908
+    /**
909
+     * Get the node with file $id for $user
910
+     *
911
+     * @param string $userId
912
+     * @param int $id
913
+     * @return \OCP\Files\File|\OCP\Files\Folder
914
+     * @throws InvalidShare
915
+     */
916
+    private function getNode($userId, $id) {
917
+        try {
918
+            $userFolder = $this->rootFolder->getUserFolder($userId);
919
+        } catch (NotFoundException $e) {
920
+            throw new InvalidShare();
921
+        }
922
+
923
+        $nodes = $userFolder->getById($id);
924
+
925
+        if (empty($nodes)) {
926
+            throw new InvalidShare();
927
+        }
928
+
929
+        return $nodes[0];
930
+    }
931
+
932
+    /**
933
+     * A user is deleted from the system
934
+     * So clean up the relevant shares.
935
+     *
936
+     * @param string $uid
937
+     * @param int $shareType
938
+     */
939
+    public function userDeleted($uid, $shareType) {
940
+        //TODO: probabaly a good idea to send unshare info to remote servers
941
+
942
+        $qb = $this->dbConnection->getQueryBuilder();
943
+
944
+        $qb->delete('share')
945
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
946
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
947
+            ->execute();
948
+    }
949
+
950
+    /**
951
+     * This provider does not handle groups
952
+     *
953
+     * @param string $gid
954
+     */
955
+    public function groupDeleted($gid) {
956
+        // We don't handle groups here
957
+    }
958
+
959
+    /**
960
+     * This provider does not handle groups
961
+     *
962
+     * @param string $uid
963
+     * @param string $gid
964
+     */
965
+    public function userDeletedFromGroup($uid, $gid) {
966
+        // We don't handle groups here
967
+    }
968
+
969
+    /**
970
+     * check if users from other Nextcloud instances are allowed to mount public links share by this instance
971
+     *
972
+     * @return bool
973
+     */
974
+    public function isOutgoingServer2serverShareEnabled() {
975
+        if ($this->gsConfig->onlyInternalFederation()) {
976
+            return false;
977
+        }
978
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
979
+        return ($result === 'yes');
980
+    }
981
+
982
+    /**
983
+     * check if users are allowed to mount public links from other Nextclouds
984
+     *
985
+     * @return bool
986
+     */
987
+    public function isIncomingServer2serverShareEnabled() {
988
+        if ($this->gsConfig->onlyInternalFederation()) {
989
+            return false;
990
+        }
991
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
992
+        return ($result === 'yes');
993
+    }
994
+
995
+
996
+    /**
997
+     * check if users from other Nextcloud instances are allowed to send federated group shares
998
+     *
999
+     * @return bool
1000
+     */
1001
+    public function isOutgoingServer2serverGroupShareEnabled() {
1002
+        if ($this->gsConfig->onlyInternalFederation()) {
1003
+            return false;
1004
+        }
1005
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
1006
+        return ($result === 'yes');
1007
+    }
1008
+
1009
+    /**
1010
+     * check if users are allowed to receive federated group shares
1011
+     *
1012
+     * @return bool
1013
+     */
1014
+    public function isIncomingServer2serverGroupShareEnabled() {
1015
+        if ($this->gsConfig->onlyInternalFederation()) {
1016
+            return false;
1017
+        }
1018
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
1019
+        return ($result === 'yes');
1020
+    }
1021
+
1022
+    /**
1023
+     * check if federated group sharing is supported, therefore the OCM API need to be enabled
1024
+     *
1025
+     * @return bool
1026
+     */
1027
+    public function isFederatedGroupSharingSupported() {
1028
+        return $this->cloudFederationProviderManager->isReady();
1029
+    }
1030
+
1031
+    /**
1032
+     * Check if querying sharees on the lookup server is enabled
1033
+     *
1034
+     * @return bool
1035
+     */
1036
+    public function isLookupServerQueriesEnabled() {
1037
+        // in a global scale setup we should always query the lookup server
1038
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1039
+            return true;
1040
+        }
1041
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no');
1042
+        return ($result === 'yes');
1043
+    }
1044
+
1045
+
1046
+    /**
1047
+     * Check if it is allowed to publish user specific data to the lookup server
1048
+     *
1049
+     * @return bool
1050
+     */
1051
+    public function isLookupServerUploadEnabled() {
1052
+        // in a global scale setup the admin is responsible to keep the lookup server up-to-date
1053
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1054
+            return false;
1055
+        }
1056
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1057
+        return ($result === 'yes');
1058
+    }
1059
+
1060
+    /**
1061
+     * @inheritdoc
1062
+     */
1063
+    public function getAccessList($nodes, $currentAccess) {
1064
+        $ids = [];
1065
+        foreach ($nodes as $node) {
1066
+            $ids[] = $node->getId();
1067
+        }
1068
+
1069
+        $qb = $this->dbConnection->getQueryBuilder();
1070
+        $qb->select('share_with', 'token', 'file_source')
1071
+            ->from('share')
1072
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
1073
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1074
+            ->andWhere($qb->expr()->orX(
1075
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1076
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1077
+            ));
1078
+        $cursor = $qb->execute();
1079
+
1080
+        if ($currentAccess === false) {
1081
+            $remote = $cursor->fetch() !== false;
1082
+            $cursor->closeCursor();
1083
+
1084
+            return ['remote' => $remote];
1085
+        }
1086
+
1087
+        $remote = [];
1088
+        while ($row = $cursor->fetch()) {
1089
+            $remote[$row['share_with']] = [
1090
+                'node_id' => $row['file_source'],
1091
+                'token' => $row['token'],
1092
+            ];
1093
+        }
1094
+        $cursor->closeCursor();
1095
+
1096
+        return ['remote' => $remote];
1097
+    }
1098 1098
 }
Please login to merge, or discard this patch.
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -214,7 +214,7 @@  discard block
 block discarded – undo
214 214
 		if ($remoteShare) {
215 215
 			try {
216 216
 				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
217
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
217
+				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_'.time(), $shareType);
218 218
 				$share->setId($shareId);
219 219
 				list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
220 220
 				// remote share was create successfully if we get a valid token as return
@@ -296,7 +296,7 @@  discard block
 block discarded – undo
296 296
 			$failure = true;
297 297
 		}
298 298
 
299
-		if($failure) {
299
+		if ($failure) {
300 300
 			$this->removeShareFromTableById($shareId);
301 301
 			$message_t = $this->l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate.',
302 302
 				[$share->getNode()->getName(), $share->getSharedWith()]);
@@ -348,7 +348,7 @@  discard block
 block discarded – undo
348 348
 			->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
349 349
 		$result = $query->execute()->fetchAll();
350 350
 
351
-		if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
351
+		if (isset($result[0]) && (int) $result[0]['remote_id'] > 0) {
352 352
 			return $result[0];
353 353
 		}
354 354
 
@@ -391,7 +391,7 @@  discard block
 block discarded – undo
391 391
 		$qb->execute();
392 392
 		$id = $qb->getLastInsertId();
393 393
 
394
-		return (int)$id;
394
+		return (int) $id;
395 395
 	}
396 396
 
397 397
 	/**
@@ -481,14 +481,14 @@  discard block
 block discarded – undo
481 481
 	public function getRemoteId(IShare $share) {
482 482
 		$query = $this->dbConnection->getQueryBuilder();
483 483
 		$query->select('remote_id')->from('federated_reshares')
484
-			->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
484
+			->where($query->expr()->eq('share_id', $query->createNamedParameter((int) $share->getId())));
485 485
 		$data = $query->execute()->fetch();
486 486
 
487 487
 		if (!is_array($data) || !isset($data['remote_id'])) {
488 488
 			throw new ShareNotFound();
489 489
 		}
490 490
 
491
-		return (int)$data['remote_id'];
491
+		return (int) $data['remote_id'];
492 492
 	}
493 493
 
494 494
 	/**
@@ -519,7 +519,7 @@  discard block
 block discarded – undo
519 519
 			->orderBy('id');
520 520
 
521 521
 		$cursor = $qb->execute();
522
-		while($data = $cursor->fetch()) {
522
+		while ($data = $cursor->fetch()) {
523 523
 			$children[] = $this->createShareObject($data);
524 524
 		}
525 525
 		$cursor->closeCursor();
@@ -641,7 +641,7 @@  discard block
 block discarded – undo
641 641
 			);
642 642
 		}
643 643
 
644
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
644
+		$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
645 645
 		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
646 646
 
647 647
 		$qb->orderBy('id');
@@ -704,7 +704,7 @@  discard block
 block discarded – undo
704 704
 
705 705
 		$cursor = $qb->execute();
706 706
 		$shares = [];
707
-		while($data = $cursor->fetch()) {
707
+		while ($data = $cursor->fetch()) {
708 708
 			$shares[] = $this->createShareObject($data);
709 709
 		}
710 710
 		$cursor->closeCursor();
@@ -728,7 +728,7 @@  discard block
 block discarded – undo
728 728
 		$cursor->closeCursor();
729 729
 
730 730
 		if ($data === false) {
731
-			throw new ShareNotFound('Can not find share with ID: ' . $id);
731
+			throw new ShareNotFound('Can not find share with ID: '.$id);
732 732
 		}
733 733
 
734 734
 		try {
@@ -757,7 +757,7 @@  discard block
 block discarded – undo
757 757
 			->execute();
758 758
 
759 759
 		$shares = [];
760
-		while($data = $cursor->fetch()) {
760
+		while ($data = $cursor->fetch()) {
761 761
 			$shares[] = $this->createShareObject($data);
762 762
 		}
763 763
 		$cursor->closeCursor();
@@ -796,7 +796,7 @@  discard block
 block discarded – undo
796 796
 
797 797
 		$cursor = $qb->execute();
798 798
 
799
-		while($data = $cursor->fetch()) {
799
+		while ($data = $cursor->fetch()) {
800 800
 			$shares[] = $this->createShareObject($data);
801 801
 		}
802 802
 		$cursor->closeCursor();
@@ -873,15 +873,15 @@  discard block
 block discarded – undo
873 873
 	private function createShareObject($data) {
874 874
 
875 875
 		$share = new Share($this->rootFolder, $this->userManager);
876
-		$share->setId((int)$data['id'])
877
-			->setShareType((int)$data['share_type'])
878
-			->setPermissions((int)$data['permissions'])
876
+		$share->setId((int) $data['id'])
877
+			->setShareType((int) $data['share_type'])
878
+			->setPermissions((int) $data['permissions'])
879 879
 			->setTarget($data['file_target'])
880
-			->setMailSend((bool)$data['mail_send'])
880
+			->setMailSend((bool) $data['mail_send'])
881 881
 			->setToken($data['token']);
882 882
 
883 883
 		$shareTime = new \DateTime();
884
-		$shareTime->setTimestamp((int)$data['stime']);
884
+		$shareTime->setTimestamp((int) $data['stime']);
885 885
 		$share->setShareTime($shareTime);
886 886
 		$share->setSharedWith($data['share_with']);
887 887
 
@@ -891,13 +891,13 @@  discard block
 block discarded – undo
891 891
 		} else {
892 892
 			//OLD SHARE
893 893
 			$share->setSharedBy($data['uid_owner']);
894
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
894
+			$path = $this->getNode($share->getSharedBy(), (int) $data['file_source']);
895 895
 
896 896
 			$owner = $path->getOwner();
897 897
 			$share->setShareOwner($owner->getUID());
898 898
 		}
899 899
 
900
-		$share->setNodeId((int)$data['file_source']);
900
+		$share->setNodeId((int) $data['file_source']);
901 901
 		$share->setNodeType($data['item_type']);
902 902
 
903 903
 		$share->setProviderId($this->identifier());
Please login to merge, or discard this patch.
apps/files_external/lib/config.php 2 patches
Indentation   +367 added lines, -367 removed lines patch added patch discarded remove patch
@@ -52,371 +52,371 @@
 block discarded – undo
52 52
  * Class to configure mount.json globally and for users
53 53
  */
54 54
 class OC_Mount_Config {
55
-	// TODO: make this class non-static and give it a proper namespace
56
-
57
-	const MOUNT_TYPE_GLOBAL = 'global';
58
-	const MOUNT_TYPE_GROUP = 'group';
59
-	const MOUNT_TYPE_USER = 'user';
60
-	const MOUNT_TYPE_PERSONAL = 'personal';
61
-
62
-	// whether to skip backend test (for unit tests, as this static class is not mockable)
63
-	public static $skipTest = false;
64
-
65
-	/** @var Application */
66
-	public static $app;
67
-
68
-	/**
69
-	 * @param string $class
70
-	 * @param array $definition
71
-	 * @return bool
72
-	 * @deprecated 8.2.0 use \OCA\Files_External\Service\BackendService::registerBackend()
73
-	 */
74
-	public static function registerBackend($class, $definition) {
75
-		$backendService = self::$app->getContainer()->query(BackendService::class);
76
-		$auth = self::$app->getContainer()->query(Builtin::class);
77
-
78
-		$backendService->registerBackend(new LegacyBackend($class, $definition, $auth));
79
-
80
-		return true;
81
-	}
82
-
83
-	/**
84
-	 * Returns the mount points for the given user.
85
-	 * The mount point is relative to the data directory.
86
-	 *
87
-	 * @param string $uid user
88
-	 * @return array of mount point string as key, mountpoint config as value
89
-	 *
90
-	 * @deprecated 8.2.0 use UserGlobalStoragesService::getStorages() and UserStoragesService::getStorages()
91
-	 */
92
-	public static function getAbsoluteMountPoints($uid) {
93
-		$mountPoints = array();
94
-
95
-		$userGlobalStoragesService = self::$app->getContainer()->query(UserGlobalStoragesService::class);
96
-		$userStoragesService = self::$app->getContainer()->query(UserStoragesService::class);
97
-		$user = self::$app->getContainer()->query(IUserManager::class)->get($uid);
98
-
99
-		$userGlobalStoragesService->setUser($user);
100
-		$userStoragesService->setUser($user);
101
-
102
-		foreach ($userGlobalStoragesService->getStorages() as $storage) {
103
-			/** @var \OCA\Files_External\Lib\StorageConfig $storage */
104
-			$mountPoint = '/'.$uid.'/files'.$storage->getMountPoint();
105
-			$mountEntry = self::prepareMountPointEntry($storage, false);
106
-			foreach ($mountEntry['options'] as &$option) {
107
-				$option = self::setUserVars($uid, $option);
108
-			}
109
-			$mountPoints[$mountPoint] = $mountEntry;
110
-		}
111
-
112
-		foreach ($userStoragesService->getStorages() as $storage) {
113
-			$mountPoint = '/'.$uid.'/files'.$storage->getMountPoint();
114
-			$mountEntry = self::prepareMountPointEntry($storage, true);
115
-			foreach ($mountEntry['options'] as &$option) {
116
-				$option = self::setUserVars($uid, $option);
117
-			}
118
-			$mountPoints[$mountPoint] = $mountEntry;
119
-		}
120
-
121
-		$userGlobalStoragesService->resetUser();
122
-		$userStoragesService->resetUser();
123
-
124
-		return $mountPoints;
125
-	}
126
-
127
-	/**
128
-	 * Get the system mount points
129
-	 *
130
-	 * @return array
131
-	 *
132
-	 * @deprecated 8.2.0 use GlobalStoragesService::getStorages()
133
-	 */
134
-	public static function getSystemMountPoints() {
135
-		$mountPoints = [];
136
-		$service = self::$app->getContainer()->query(GlobalStoragesService::class);
137
-
138
-		foreach ($service->getStorages() as $storage) {
139
-			$mountPoints[] = self::prepareMountPointEntry($storage, false);
140
-		}
141
-
142
-		return $mountPoints;
143
-	}
144
-
145
-	/**
146
-	 * Get the personal mount points of the current user
147
-	 *
148
-	 * @return array
149
-	 *
150
-	 * @deprecated 8.2.0 use UserStoragesService::getStorages()
151
-	 */
152
-	public static function getPersonalMountPoints() {
153
-		$mountPoints = [];
154
-		$service = self::$app->getContainer()->query(UserStoragesService::class);
155
-
156
-		foreach ($service->getStorages() as $storage) {
157
-			$mountPoints[] = self::prepareMountPointEntry($storage, true);
158
-		}
159
-
160
-		return $mountPoints;
161
-	}
162
-
163
-	/**
164
-	 * Convert a StorageConfig to the legacy mountPoints array format
165
-	 * There's a lot of extra information in here, to satisfy all of the legacy functions
166
-	 *
167
-	 * @param StorageConfig $storage
168
-	 * @param bool $isPersonal
169
-	 * @return array
170
-	 */
171
-	private static function prepareMountPointEntry(StorageConfig $storage, $isPersonal) {
172
-		$mountEntry = [];
173
-
174
-		$mountEntry['mountpoint'] = substr($storage->getMountPoint(), 1); // remove leading slash
175
-		$mountEntry['class'] = $storage->getBackend()->getIdentifier();
176
-		$mountEntry['backend'] = $storage->getBackend()->getText();
177
-		$mountEntry['authMechanism'] = $storage->getAuthMechanism()->getIdentifier();
178
-		$mountEntry['personal'] = $isPersonal;
179
-		$mountEntry['options'] = self::decryptPasswords($storage->getBackendOptions());
180
-		$mountEntry['mountOptions'] = $storage->getMountOptions();
181
-		$mountEntry['priority'] = $storage->getPriority();
182
-		$mountEntry['applicable'] = [
183
-			'groups' => $storage->getApplicableGroups(),
184
-			'users' => $storage->getApplicableUsers(),
185
-		];
186
-		// if mountpoint is applicable to all users the old API expects ['all']
187
-		if (empty($mountEntry['applicable']['groups']) && empty($mountEntry['applicable']['users'])) {
188
-			$mountEntry['applicable']['users'] = ['all'];
189
-		}
190
-
191
-		$mountEntry['id'] = $storage->getId();
192
-
193
-		return $mountEntry;
194
-	}
195
-
196
-	/**
197
-	 * fill in the correct values for $user
198
-	 *
199
-	 * @param string $user user value
200
-	 * @param string|array $input
201
-	 * @return string
202
-	 */
203
-	public static function setUserVars($user, $input) {
204
-		if (is_array($input)) {
205
-			foreach ($input as &$value) {
206
-				if (is_string($value)) {
207
-					$value = str_replace('$user', $user, $value);
208
-				}
209
-			}
210
-		} else {
211
-			if (is_string($input)) {
212
-				$input = str_replace('$user', $user, $input);
213
-			}
214
-		}
215
-		return $input;
216
-	}
217
-
218
-	/**
219
-	 * Test connecting using the given backend configuration
220
-	 *
221
-	 * @param string $class backend class name
222
-	 * @param array $options backend configuration options
223
-	 * @param boolean $isPersonal
224
-	 * @return int see self::STATUS_*
225
-	 * @throws Exception
226
-	 */
227
-	public static function getBackendStatus($class, $options, $isPersonal, $testOnly = true) {
228
-		if (self::$skipTest) {
229
-			return StorageNotAvailableException::STATUS_SUCCESS;
230
-		}
231
-		foreach ($options as &$option) {
232
-			$option = self::setUserVars(OCP\User::getUser(), $option);
233
-		}
234
-		if (class_exists($class)) {
235
-			try {
236
-				/** @var \OC\Files\Storage\Common $storage */
237
-				$storage = new $class($options);
238
-
239
-				try {
240
-					$result = $storage->test($isPersonal, $testOnly);
241
-					$storage->setAvailability($result);
242
-					if ($result) {
243
-						return StorageNotAvailableException::STATUS_SUCCESS;
244
-					}
245
-				} catch (\Exception $e) {
246
-					$storage->setAvailability(false);
247
-					throw $e;
248
-				}
249
-			} catch (Exception $exception) {
250
-				\OC::$server->getLogger()->logException($exception, ['app' => 'files_external']);
251
-				throw $exception;
252
-			}
253
-		}
254
-		return StorageNotAvailableException::STATUS_ERROR;
255
-	}
256
-
257
-	/**
258
-	 * Read the mount points in the config file into an array
259
-	 *
260
-	 * @param string|null $user If not null, personal for $user, otherwise system
261
-	 * @return array
262
-	 */
263
-	public static function readData($user = null) {
264
-		if (isset($user)) {
265
-			$jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
266
-		} else {
267
-			$config = \OC::$server->getConfig();
268
-			$datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
269
-			$jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
270
-		}
271
-		if (is_file($jsonFile)) {
272
-			$mountPoints = json_decode(file_get_contents($jsonFile), true);
273
-			if (is_array($mountPoints)) {
274
-				return $mountPoints;
275
-			}
276
-		}
277
-		return array();
278
-	}
279
-
280
-	/**
281
-	 * Get backend dependency message
282
-	 * TODO: move into AppFramework along with templates
283
-	 *
284
-	 * @param Backend[] $backends
285
-	 * @return string
286
-	 */
287
-	public static function dependencyMessage($backends) {
288
-		$l = \OC::$server->getL10N('files_external');
289
-		$message = '';
290
-		$dependencyGroups = [];
291
-
292
-		foreach ($backends as $backend) {
293
-			foreach ($backend->checkDependencies() as $dependency) {
294
-				if ($message = $dependency->getMessage()) {
295
-					$message .= '<p>' . $message . '</p>';
296
-				} else {
297
-					$dependencyGroups[$dependency->getDependency()][] = $backend;
298
-				}
299
-			}
300
-		}
301
-
302
-		foreach ($dependencyGroups as $module => $dependants) {
303
-			$backends = implode(', ', array_map(function($backend) {
304
-				return '"' . $backend->getText() . '"';
305
-			}, $dependants));
306
-			$message .= '<p>' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends) . '</p>';
307
-		}
308
-
309
-		return $message;
310
-	}
311
-
312
-	/**
313
-	 * Returns a dependency missing message
314
-	 *
315
-	 * @param \OCP\IL10N $l
316
-	 * @param string $module
317
-	 * @param string $backend
318
-	 * @return string
319
-	 */
320
-	private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
321
-		switch (strtolower($module)) {
322
-			case 'curl':
323
-				return (string)$l->t('The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
324
-			case 'ftp':
325
-				return (string)$l->t('The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
326
-			default:
327
-				return (string)$l->t('"%1$s" is not installed. Mounting of %2$s is not possible. Please ask your system administrator to install it.', [$module, $backend]);
328
-		}
329
-	}
330
-
331
-	/**
332
-	 * Encrypt passwords in the given config options
333
-	 *
334
-	 * @param array $options mount options
335
-	 * @return array updated options
336
-	 */
337
-	public static function encryptPasswords($options) {
338
-		if (isset($options['password'])) {
339
-			$options['password_encrypted'] = self::encryptPassword($options['password']);
340
-			// do not unset the password, we want to keep the keys order
341
-			// on load... because that's how the UI currently works
342
-			$options['password'] = '';
343
-		}
344
-		return $options;
345
-	}
346
-
347
-	/**
348
-	 * Decrypt passwords in the given config options
349
-	 *
350
-	 * @param array $options mount options
351
-	 * @return array updated options
352
-	 */
353
-	public static function decryptPasswords($options) {
354
-		// note: legacy options might still have the unencrypted password in the "password" field
355
-		if (isset($options['password_encrypted'])) {
356
-			$options['password'] = self::decryptPassword($options['password_encrypted']);
357
-			unset($options['password_encrypted']);
358
-		}
359
-		return $options;
360
-	}
361
-
362
-	/**
363
-	 * Encrypt a single password
364
-	 *
365
-	 * @param string $password plain text password
366
-	 * @return string encrypted password
367
-	 */
368
-	private static function encryptPassword($password) {
369
-		$cipher = self::getCipher();
370
-		$iv = \OC::$server->getSecureRandom()->generate(16);
371
-		$cipher->setIV($iv);
372
-		return base64_encode($iv . $cipher->encrypt($password));
373
-	}
374
-
375
-	/**
376
-	 * Decrypts a single password
377
-	 *
378
-	 * @param string $encryptedPassword encrypted password
379
-	 * @return string plain text password
380
-	 */
381
-	private static function decryptPassword($encryptedPassword) {
382
-		$cipher = self::getCipher();
383
-		$binaryPassword = base64_decode($encryptedPassword);
384
-		$iv = substr($binaryPassword, 0, 16);
385
-		$cipher->setIV($iv);
386
-		$binaryPassword = substr($binaryPassword, 16);
387
-		return $cipher->decrypt($binaryPassword);
388
-	}
389
-
390
-	/**
391
-	 * Returns the encryption cipher
392
-	 *
393
-	 * @return AES
394
-	 */
395
-	private static function getCipher() {
396
-		$cipher = new AES(AES::MODE_CBC);
397
-		$cipher->setKey(\OC::$server->getConfig()->getSystemValue('passwordsalt', null));
398
-		return $cipher;
399
-	}
400
-
401
-	/**
402
-	 * Computes a hash based on the given configuration.
403
-	 * This is mostly used to find out whether configurations
404
-	 * are the same.
405
-	 *
406
-	 * @param array $config
407
-	 * @return string
408
-	 */
409
-	public static function makeConfigHash($config) {
410
-		$data = json_encode(
411
-			array(
412
-				'c' => $config['backend'],
413
-				'a' => $config['authMechanism'],
414
-				'm' => $config['mountpoint'],
415
-				'o' => $config['options'],
416
-				'p' => isset($config['priority']) ? $config['priority'] : -1,
417
-				'mo' => isset($config['mountOptions']) ? $config['mountOptions'] : [],
418
-			)
419
-		);
420
-		return hash('md5', $data);
421
-	}
55
+    // TODO: make this class non-static and give it a proper namespace
56
+
57
+    const MOUNT_TYPE_GLOBAL = 'global';
58
+    const MOUNT_TYPE_GROUP = 'group';
59
+    const MOUNT_TYPE_USER = 'user';
60
+    const MOUNT_TYPE_PERSONAL = 'personal';
61
+
62
+    // whether to skip backend test (for unit tests, as this static class is not mockable)
63
+    public static $skipTest = false;
64
+
65
+    /** @var Application */
66
+    public static $app;
67
+
68
+    /**
69
+     * @param string $class
70
+     * @param array $definition
71
+     * @return bool
72
+     * @deprecated 8.2.0 use \OCA\Files_External\Service\BackendService::registerBackend()
73
+     */
74
+    public static function registerBackend($class, $definition) {
75
+        $backendService = self::$app->getContainer()->query(BackendService::class);
76
+        $auth = self::$app->getContainer()->query(Builtin::class);
77
+
78
+        $backendService->registerBackend(new LegacyBackend($class, $definition, $auth));
79
+
80
+        return true;
81
+    }
82
+
83
+    /**
84
+     * Returns the mount points for the given user.
85
+     * The mount point is relative to the data directory.
86
+     *
87
+     * @param string $uid user
88
+     * @return array of mount point string as key, mountpoint config as value
89
+     *
90
+     * @deprecated 8.2.0 use UserGlobalStoragesService::getStorages() and UserStoragesService::getStorages()
91
+     */
92
+    public static function getAbsoluteMountPoints($uid) {
93
+        $mountPoints = array();
94
+
95
+        $userGlobalStoragesService = self::$app->getContainer()->query(UserGlobalStoragesService::class);
96
+        $userStoragesService = self::$app->getContainer()->query(UserStoragesService::class);
97
+        $user = self::$app->getContainer()->query(IUserManager::class)->get($uid);
98
+
99
+        $userGlobalStoragesService->setUser($user);
100
+        $userStoragesService->setUser($user);
101
+
102
+        foreach ($userGlobalStoragesService->getStorages() as $storage) {
103
+            /** @var \OCA\Files_External\Lib\StorageConfig $storage */
104
+            $mountPoint = '/'.$uid.'/files'.$storage->getMountPoint();
105
+            $mountEntry = self::prepareMountPointEntry($storage, false);
106
+            foreach ($mountEntry['options'] as &$option) {
107
+                $option = self::setUserVars($uid, $option);
108
+            }
109
+            $mountPoints[$mountPoint] = $mountEntry;
110
+        }
111
+
112
+        foreach ($userStoragesService->getStorages() as $storage) {
113
+            $mountPoint = '/'.$uid.'/files'.$storage->getMountPoint();
114
+            $mountEntry = self::prepareMountPointEntry($storage, true);
115
+            foreach ($mountEntry['options'] as &$option) {
116
+                $option = self::setUserVars($uid, $option);
117
+            }
118
+            $mountPoints[$mountPoint] = $mountEntry;
119
+        }
120
+
121
+        $userGlobalStoragesService->resetUser();
122
+        $userStoragesService->resetUser();
123
+
124
+        return $mountPoints;
125
+    }
126
+
127
+    /**
128
+     * Get the system mount points
129
+     *
130
+     * @return array
131
+     *
132
+     * @deprecated 8.2.0 use GlobalStoragesService::getStorages()
133
+     */
134
+    public static function getSystemMountPoints() {
135
+        $mountPoints = [];
136
+        $service = self::$app->getContainer()->query(GlobalStoragesService::class);
137
+
138
+        foreach ($service->getStorages() as $storage) {
139
+            $mountPoints[] = self::prepareMountPointEntry($storage, false);
140
+        }
141
+
142
+        return $mountPoints;
143
+    }
144
+
145
+    /**
146
+     * Get the personal mount points of the current user
147
+     *
148
+     * @return array
149
+     *
150
+     * @deprecated 8.2.0 use UserStoragesService::getStorages()
151
+     */
152
+    public static function getPersonalMountPoints() {
153
+        $mountPoints = [];
154
+        $service = self::$app->getContainer()->query(UserStoragesService::class);
155
+
156
+        foreach ($service->getStorages() as $storage) {
157
+            $mountPoints[] = self::prepareMountPointEntry($storage, true);
158
+        }
159
+
160
+        return $mountPoints;
161
+    }
162
+
163
+    /**
164
+     * Convert a StorageConfig to the legacy mountPoints array format
165
+     * There's a lot of extra information in here, to satisfy all of the legacy functions
166
+     *
167
+     * @param StorageConfig $storage
168
+     * @param bool $isPersonal
169
+     * @return array
170
+     */
171
+    private static function prepareMountPointEntry(StorageConfig $storage, $isPersonal) {
172
+        $mountEntry = [];
173
+
174
+        $mountEntry['mountpoint'] = substr($storage->getMountPoint(), 1); // remove leading slash
175
+        $mountEntry['class'] = $storage->getBackend()->getIdentifier();
176
+        $mountEntry['backend'] = $storage->getBackend()->getText();
177
+        $mountEntry['authMechanism'] = $storage->getAuthMechanism()->getIdentifier();
178
+        $mountEntry['personal'] = $isPersonal;
179
+        $mountEntry['options'] = self::decryptPasswords($storage->getBackendOptions());
180
+        $mountEntry['mountOptions'] = $storage->getMountOptions();
181
+        $mountEntry['priority'] = $storage->getPriority();
182
+        $mountEntry['applicable'] = [
183
+            'groups' => $storage->getApplicableGroups(),
184
+            'users' => $storage->getApplicableUsers(),
185
+        ];
186
+        // if mountpoint is applicable to all users the old API expects ['all']
187
+        if (empty($mountEntry['applicable']['groups']) && empty($mountEntry['applicable']['users'])) {
188
+            $mountEntry['applicable']['users'] = ['all'];
189
+        }
190
+
191
+        $mountEntry['id'] = $storage->getId();
192
+
193
+        return $mountEntry;
194
+    }
195
+
196
+    /**
197
+     * fill in the correct values for $user
198
+     *
199
+     * @param string $user user value
200
+     * @param string|array $input
201
+     * @return string
202
+     */
203
+    public static function setUserVars($user, $input) {
204
+        if (is_array($input)) {
205
+            foreach ($input as &$value) {
206
+                if (is_string($value)) {
207
+                    $value = str_replace('$user', $user, $value);
208
+                }
209
+            }
210
+        } else {
211
+            if (is_string($input)) {
212
+                $input = str_replace('$user', $user, $input);
213
+            }
214
+        }
215
+        return $input;
216
+    }
217
+
218
+    /**
219
+     * Test connecting using the given backend configuration
220
+     *
221
+     * @param string $class backend class name
222
+     * @param array $options backend configuration options
223
+     * @param boolean $isPersonal
224
+     * @return int see self::STATUS_*
225
+     * @throws Exception
226
+     */
227
+    public static function getBackendStatus($class, $options, $isPersonal, $testOnly = true) {
228
+        if (self::$skipTest) {
229
+            return StorageNotAvailableException::STATUS_SUCCESS;
230
+        }
231
+        foreach ($options as &$option) {
232
+            $option = self::setUserVars(OCP\User::getUser(), $option);
233
+        }
234
+        if (class_exists($class)) {
235
+            try {
236
+                /** @var \OC\Files\Storage\Common $storage */
237
+                $storage = new $class($options);
238
+
239
+                try {
240
+                    $result = $storage->test($isPersonal, $testOnly);
241
+                    $storage->setAvailability($result);
242
+                    if ($result) {
243
+                        return StorageNotAvailableException::STATUS_SUCCESS;
244
+                    }
245
+                } catch (\Exception $e) {
246
+                    $storage->setAvailability(false);
247
+                    throw $e;
248
+                }
249
+            } catch (Exception $exception) {
250
+                \OC::$server->getLogger()->logException($exception, ['app' => 'files_external']);
251
+                throw $exception;
252
+            }
253
+        }
254
+        return StorageNotAvailableException::STATUS_ERROR;
255
+    }
256
+
257
+    /**
258
+     * Read the mount points in the config file into an array
259
+     *
260
+     * @param string|null $user If not null, personal for $user, otherwise system
261
+     * @return array
262
+     */
263
+    public static function readData($user = null) {
264
+        if (isset($user)) {
265
+            $jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
266
+        } else {
267
+            $config = \OC::$server->getConfig();
268
+            $datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
269
+            $jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
270
+        }
271
+        if (is_file($jsonFile)) {
272
+            $mountPoints = json_decode(file_get_contents($jsonFile), true);
273
+            if (is_array($mountPoints)) {
274
+                return $mountPoints;
275
+            }
276
+        }
277
+        return array();
278
+    }
279
+
280
+    /**
281
+     * Get backend dependency message
282
+     * TODO: move into AppFramework along with templates
283
+     *
284
+     * @param Backend[] $backends
285
+     * @return string
286
+     */
287
+    public static function dependencyMessage($backends) {
288
+        $l = \OC::$server->getL10N('files_external');
289
+        $message = '';
290
+        $dependencyGroups = [];
291
+
292
+        foreach ($backends as $backend) {
293
+            foreach ($backend->checkDependencies() as $dependency) {
294
+                if ($message = $dependency->getMessage()) {
295
+                    $message .= '<p>' . $message . '</p>';
296
+                } else {
297
+                    $dependencyGroups[$dependency->getDependency()][] = $backend;
298
+                }
299
+            }
300
+        }
301
+
302
+        foreach ($dependencyGroups as $module => $dependants) {
303
+            $backends = implode(', ', array_map(function($backend) {
304
+                return '"' . $backend->getText() . '"';
305
+            }, $dependants));
306
+            $message .= '<p>' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends) . '</p>';
307
+        }
308
+
309
+        return $message;
310
+    }
311
+
312
+    /**
313
+     * Returns a dependency missing message
314
+     *
315
+     * @param \OCP\IL10N $l
316
+     * @param string $module
317
+     * @param string $backend
318
+     * @return string
319
+     */
320
+    private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
321
+        switch (strtolower($module)) {
322
+            case 'curl':
323
+                return (string)$l->t('The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
324
+            case 'ftp':
325
+                return (string)$l->t('The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
326
+            default:
327
+                return (string)$l->t('"%1$s" is not installed. Mounting of %2$s is not possible. Please ask your system administrator to install it.', [$module, $backend]);
328
+        }
329
+    }
330
+
331
+    /**
332
+     * Encrypt passwords in the given config options
333
+     *
334
+     * @param array $options mount options
335
+     * @return array updated options
336
+     */
337
+    public static function encryptPasswords($options) {
338
+        if (isset($options['password'])) {
339
+            $options['password_encrypted'] = self::encryptPassword($options['password']);
340
+            // do not unset the password, we want to keep the keys order
341
+            // on load... because that's how the UI currently works
342
+            $options['password'] = '';
343
+        }
344
+        return $options;
345
+    }
346
+
347
+    /**
348
+     * Decrypt passwords in the given config options
349
+     *
350
+     * @param array $options mount options
351
+     * @return array updated options
352
+     */
353
+    public static function decryptPasswords($options) {
354
+        // note: legacy options might still have the unencrypted password in the "password" field
355
+        if (isset($options['password_encrypted'])) {
356
+            $options['password'] = self::decryptPassword($options['password_encrypted']);
357
+            unset($options['password_encrypted']);
358
+        }
359
+        return $options;
360
+    }
361
+
362
+    /**
363
+     * Encrypt a single password
364
+     *
365
+     * @param string $password plain text password
366
+     * @return string encrypted password
367
+     */
368
+    private static function encryptPassword($password) {
369
+        $cipher = self::getCipher();
370
+        $iv = \OC::$server->getSecureRandom()->generate(16);
371
+        $cipher->setIV($iv);
372
+        return base64_encode($iv . $cipher->encrypt($password));
373
+    }
374
+
375
+    /**
376
+     * Decrypts a single password
377
+     *
378
+     * @param string $encryptedPassword encrypted password
379
+     * @return string plain text password
380
+     */
381
+    private static function decryptPassword($encryptedPassword) {
382
+        $cipher = self::getCipher();
383
+        $binaryPassword = base64_decode($encryptedPassword);
384
+        $iv = substr($binaryPassword, 0, 16);
385
+        $cipher->setIV($iv);
386
+        $binaryPassword = substr($binaryPassword, 16);
387
+        return $cipher->decrypt($binaryPassword);
388
+    }
389
+
390
+    /**
391
+     * Returns the encryption cipher
392
+     *
393
+     * @return AES
394
+     */
395
+    private static function getCipher() {
396
+        $cipher = new AES(AES::MODE_CBC);
397
+        $cipher->setKey(\OC::$server->getConfig()->getSystemValue('passwordsalt', null));
398
+        return $cipher;
399
+    }
400
+
401
+    /**
402
+     * Computes a hash based on the given configuration.
403
+     * This is mostly used to find out whether configurations
404
+     * are the same.
405
+     *
406
+     * @param array $config
407
+     * @return string
408
+     */
409
+    public static function makeConfigHash($config) {
410
+        $data = json_encode(
411
+            array(
412
+                'c' => $config['backend'],
413
+                'a' => $config['authMechanism'],
414
+                'm' => $config['mountpoint'],
415
+                'o' => $config['options'],
416
+                'p' => isset($config['priority']) ? $config['priority'] : -1,
417
+                'mo' => isset($config['mountOptions']) ? $config['mountOptions'] : [],
418
+            )
419
+        );
420
+        return hash('md5', $data);
421
+    }
422 422
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -262,11 +262,11 @@  discard block
 block discarded – undo
262 262
 	 */
263 263
 	public static function readData($user = null) {
264 264
 		if (isset($user)) {
265
-			$jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
265
+			$jsonFile = \OC::$server->getUserManager()->get($user)->getHome().'/mount.json';
266 266
 		} else {
267 267
 			$config = \OC::$server->getConfig();
268
-			$datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
269
-			$jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
268
+			$datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data/');
269
+			$jsonFile = $config->getSystemValue('mount_file', $datadir.'/mount.json');
270 270
 		}
271 271
 		if (is_file($jsonFile)) {
272 272
 			$mountPoints = json_decode(file_get_contents($jsonFile), true);
@@ -292,7 +292,7 @@  discard block
 block discarded – undo
292 292
 		foreach ($backends as $backend) {
293 293
 			foreach ($backend->checkDependencies() as $dependency) {
294 294
 				if ($message = $dependency->getMessage()) {
295
-					$message .= '<p>' . $message . '</p>';
295
+					$message .= '<p>'.$message.'</p>';
296 296
 				} else {
297 297
 					$dependencyGroups[$dependency->getDependency()][] = $backend;
298 298
 				}
@@ -301,9 +301,9 @@  discard block
 block discarded – undo
301 301
 
302 302
 		foreach ($dependencyGroups as $module => $dependants) {
303 303
 			$backends = implode(', ', array_map(function($backend) {
304
-				return '"' . $backend->getText() . '"';
304
+				return '"'.$backend->getText().'"';
305 305
 			}, $dependants));
306
-			$message .= '<p>' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends) . '</p>';
306
+			$message .= '<p>'.OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends).'</p>';
307 307
 		}
308 308
 
309 309
 		return $message;
@@ -320,11 +320,11 @@  discard block
 block discarded – undo
320 320
 	private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
321 321
 		switch (strtolower($module)) {
322 322
 			case 'curl':
323
-				return (string)$l->t('The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
323
+				return (string) $l->t('The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
324 324
 			case 'ftp':
325
-				return (string)$l->t('The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
325
+				return (string) $l->t('The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', [$backend]);
326 326
 			default:
327
-				return (string)$l->t('"%1$s" is not installed. Mounting of %2$s is not possible. Please ask your system administrator to install it.', [$module, $backend]);
327
+				return (string) $l->t('"%1$s" is not installed. Mounting of %2$s is not possible. Please ask your system administrator to install it.', [$module, $backend]);
328 328
 		}
329 329
 	}
330 330
 
@@ -369,7 +369,7 @@  discard block
 block discarded – undo
369 369
 		$cipher = self::getCipher();
370 370
 		$iv = \OC::$server->getSecureRandom()->generate(16);
371 371
 		$cipher->setIV($iv);
372
-		return base64_encode($iv . $cipher->encrypt($password));
372
+		return base64_encode($iv.$cipher->encrypt($password));
373 373
 	}
374 374
 
375 375
 	/**
Please login to merge, or discard this patch.
apps/sharebymail/lib/ShareByMailProvider.php 2 patches
Indentation   +1092 added lines, -1092 removed lines patch added patch discarded remove patch
@@ -54,1110 +54,1110 @@
 block discarded – undo
54 54
  */
55 55
 class ShareByMailProvider implements IShareProvider {
56 56
 
57
-	/** @var  IDBConnection */
58
-	private $dbConnection;
59
-
60
-	/** @var ILogger */
61
-	private $logger;
62
-
63
-	/** @var ISecureRandom */
64
-	private $secureRandom;
65
-
66
-	/** @var IUserManager */
67
-	private $userManager;
68
-
69
-	/** @var IRootFolder */
70
-	private $rootFolder;
71
-
72
-	/** @var IL10N */
73
-	private $l;
74
-
75
-	/** @var IMailer */
76
-	private $mailer;
77
-
78
-	/** @var IURLGenerator */
79
-	private $urlGenerator;
80
-
81
-	/** @var IManager  */
82
-	private $activityManager;
83
-
84
-	/** @var SettingsManager */
85
-	private $settingsManager;
86
-
87
-	/** @var Defaults */
88
-	private $defaults;
89
-
90
-	/** @var IHasher */
91
-	private $hasher;
92
-
93
-	/** @var  CapabilitiesManager */
94
-	private $capabilitiesManager;
95
-
96
-	/**
97
-	 * Return the identifier of this provider.
98
-	 *
99
-	 * @return string Containing only [a-zA-Z0-9]
100
-	 */
101
-	public function identifier() {
102
-		return 'ocMailShare';
103
-	}
104
-
105
-	/**
106
-	 * DefaultShareProvider constructor.
107
-	 *
108
-	 * @param IDBConnection $connection
109
-	 * @param ISecureRandom $secureRandom
110
-	 * @param IUserManager $userManager
111
-	 * @param IRootFolder $rootFolder
112
-	 * @param IL10N $l
113
-	 * @param ILogger $logger
114
-	 * @param IMailer $mailer
115
-	 * @param IURLGenerator $urlGenerator
116
-	 * @param IManager $activityManager
117
-	 * @param SettingsManager $settingsManager
118
-	 * @param Defaults $defaults
119
-	 * @param IHasher $hasher
120
-	 * @param CapabilitiesManager $capabilitiesManager
121
-	 */
122
-	public function __construct(
123
-		IDBConnection $connection,
124
-		ISecureRandom $secureRandom,
125
-		IUserManager $userManager,
126
-		IRootFolder $rootFolder,
127
-		IL10N $l,
128
-		ILogger $logger,
129
-		IMailer $mailer,
130
-		IURLGenerator $urlGenerator,
131
-		IManager $activityManager,
132
-		SettingsManager $settingsManager,
133
-		Defaults $defaults,
134
-		IHasher $hasher,
135
-		CapabilitiesManager $capabilitiesManager
136
-	) {
137
-		$this->dbConnection = $connection;
138
-		$this->secureRandom = $secureRandom;
139
-		$this->userManager = $userManager;
140
-		$this->rootFolder = $rootFolder;
141
-		$this->l = $l;
142
-		$this->logger = $logger;
143
-		$this->mailer = $mailer;
144
-		$this->urlGenerator = $urlGenerator;
145
-		$this->activityManager = $activityManager;
146
-		$this->settingsManager = $settingsManager;
147
-		$this->defaults = $defaults;
148
-		$this->hasher = $hasher;
149
-		$this->capabilitiesManager = $capabilitiesManager;
150
-	}
151
-
152
-	/**
153
-	 * Share a path
154
-	 *
155
-	 * @param IShare $share
156
-	 * @return IShare The share object
157
-	 * @throws ShareNotFound
158
-	 * @throws \Exception
159
-	 */
160
-	public function create(IShare $share) {
161
-
162
-		$shareWith = $share->getSharedWith();
163
-		/*
57
+    /** @var  IDBConnection */
58
+    private $dbConnection;
59
+
60
+    /** @var ILogger */
61
+    private $logger;
62
+
63
+    /** @var ISecureRandom */
64
+    private $secureRandom;
65
+
66
+    /** @var IUserManager */
67
+    private $userManager;
68
+
69
+    /** @var IRootFolder */
70
+    private $rootFolder;
71
+
72
+    /** @var IL10N */
73
+    private $l;
74
+
75
+    /** @var IMailer */
76
+    private $mailer;
77
+
78
+    /** @var IURLGenerator */
79
+    private $urlGenerator;
80
+
81
+    /** @var IManager  */
82
+    private $activityManager;
83
+
84
+    /** @var SettingsManager */
85
+    private $settingsManager;
86
+
87
+    /** @var Defaults */
88
+    private $defaults;
89
+
90
+    /** @var IHasher */
91
+    private $hasher;
92
+
93
+    /** @var  CapabilitiesManager */
94
+    private $capabilitiesManager;
95
+
96
+    /**
97
+     * Return the identifier of this provider.
98
+     *
99
+     * @return string Containing only [a-zA-Z0-9]
100
+     */
101
+    public function identifier() {
102
+        return 'ocMailShare';
103
+    }
104
+
105
+    /**
106
+     * DefaultShareProvider constructor.
107
+     *
108
+     * @param IDBConnection $connection
109
+     * @param ISecureRandom $secureRandom
110
+     * @param IUserManager $userManager
111
+     * @param IRootFolder $rootFolder
112
+     * @param IL10N $l
113
+     * @param ILogger $logger
114
+     * @param IMailer $mailer
115
+     * @param IURLGenerator $urlGenerator
116
+     * @param IManager $activityManager
117
+     * @param SettingsManager $settingsManager
118
+     * @param Defaults $defaults
119
+     * @param IHasher $hasher
120
+     * @param CapabilitiesManager $capabilitiesManager
121
+     */
122
+    public function __construct(
123
+        IDBConnection $connection,
124
+        ISecureRandom $secureRandom,
125
+        IUserManager $userManager,
126
+        IRootFolder $rootFolder,
127
+        IL10N $l,
128
+        ILogger $logger,
129
+        IMailer $mailer,
130
+        IURLGenerator $urlGenerator,
131
+        IManager $activityManager,
132
+        SettingsManager $settingsManager,
133
+        Defaults $defaults,
134
+        IHasher $hasher,
135
+        CapabilitiesManager $capabilitiesManager
136
+    ) {
137
+        $this->dbConnection = $connection;
138
+        $this->secureRandom = $secureRandom;
139
+        $this->userManager = $userManager;
140
+        $this->rootFolder = $rootFolder;
141
+        $this->l = $l;
142
+        $this->logger = $logger;
143
+        $this->mailer = $mailer;
144
+        $this->urlGenerator = $urlGenerator;
145
+        $this->activityManager = $activityManager;
146
+        $this->settingsManager = $settingsManager;
147
+        $this->defaults = $defaults;
148
+        $this->hasher = $hasher;
149
+        $this->capabilitiesManager = $capabilitiesManager;
150
+    }
151
+
152
+    /**
153
+     * Share a path
154
+     *
155
+     * @param IShare $share
156
+     * @return IShare The share object
157
+     * @throws ShareNotFound
158
+     * @throws \Exception
159
+     */
160
+    public function create(IShare $share) {
161
+
162
+        $shareWith = $share->getSharedWith();
163
+        /*
164 164
 		 * Check if file is not already shared with the remote user
165 165
 		 */
166
-		$alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_EMAIL, $share->getNode(), 1, 0);
167
-		if (!empty($alreadyShared)) {
168
-			$message = 'Sharing %1$s failed, this item is already shared with %2$s';
169
-			$message_t = $this->l->t('Sharing %1$s failed, this item is already shared with %2$s', array($share->getNode()->getName(), $shareWith));
170
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
171
-			throw new \Exception($message_t);
172
-		}
173
-
174
-		// if the admin enforces a password for all mail shares we create a
175
-		// random password and send it to the recipient
176
-		$password = '';
177
-		$passwordEnforced = $this->settingsManager->enforcePasswordProtection();
178
-		if ($passwordEnforced) {
179
-			$password = $this->autoGeneratePassword($share);
180
-		}
181
-
182
-		$shareId = $this->createMailShare($share);
183
-		$send = $this->sendPassword($share, $password);
184
-		if ($passwordEnforced && $send === false) {
185
-			$this->sendPasswordToOwner($share, $password);
186
-		}
187
-
188
-		$this->createShareActivity($share);
189
-		$data = $this->getRawShare($shareId);
190
-
191
-		return $this->createShareObject($data);
192
-
193
-	}
194
-
195
-	/**
196
-	 * auto generate password in case of password enforcement on mail shares
197
-	 *
198
-	 * @param IShare $share
199
-	 * @return string
200
-	 * @throws \Exception
201
-	 */
202
-	protected function autoGeneratePassword($share) {
203
-		$initiatorUser = $this->userManager->get($share->getSharedBy());
204
-		$initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
205
-		$allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
206
-
207
-		if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
208
-			throw new \Exception(
209
-				$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.")
210
-			);
211
-		}
212
-
213
-		$passwordPolicy = $this->getPasswordPolicy();
214
-		$passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS;
215
-		$passwordLength = 8;
216
-		if (!empty($passwordPolicy)) {
217
-			$passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength;
218
-			$passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : '';
219
-		}
220
-
221
-		$password = $this->secureRandom->generate($passwordLength, $passwordCharset);
222
-
223
-		$share->setPassword($this->hasher->hash($password));
224
-
225
-		return $password;
226
-	}
227
-
228
-	/**
229
-	 * get password policy
230
-	 *
231
-	 * @return array
232
-	 */
233
-	protected function getPasswordPolicy() {
234
-		$capabilities = $this->capabilitiesManager->getCapabilities();
235
-		if (isset($capabilities['password_policy'])) {
236
-			return $capabilities['password_policy'];
237
-		}
238
-
239
-		return [];
240
-	}
241
-
242
-	/**
243
-	 * create activity if a file/folder was shared by mail
244
-	 *
245
-	 * @param IShare $share
246
-	 */
247
-	protected function createShareActivity(IShare $share) {
248
-
249
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
250
-
251
-		$this->publishActivity(
252
-			Activity::SUBJECT_SHARED_EMAIL_SELF,
253
-			[$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
254
-			$share->getSharedBy(),
255
-			$share->getNode()->getId(),
256
-			$userFolder->getRelativePath($share->getNode()->getPath())
257
-		);
258
-
259
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
260
-			$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
261
-			$fileId = $share->getNode()->getId();
262
-			$nodes = $ownerFolder->getById($fileId);
263
-			$ownerPath = $nodes[0]->getPath();
264
-			$this->publishActivity(
265
-				Activity::SUBJECT_SHARED_EMAIL_BY,
266
-				[$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
267
-				$share->getShareOwner(),
268
-				$fileId,
269
-				$ownerFolder->getRelativePath($ownerPath)
270
-			);
271
-		}
272
-
273
-	}
274
-
275
-	/**
276
-	 * create activity if a file/folder was shared by mail
277
-	 *
278
-	 * @param IShare $share
279
-	 * @param string $sharedWith
280
-	 * @param bool $sendToSelf
281
-	 */
282
-	protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) {
283
-
284
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
285
-
286
-		if ($sendToSelf) {
287
-			$this->publishActivity(
288
-				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
289
-				[$userFolder->getRelativePath($share->getNode()->getPath())],
290
-				$share->getSharedBy(),
291
-				$share->getNode()->getId(),
292
-				$userFolder->getRelativePath($share->getNode()->getPath())
293
-			);
294
-		} else {
295
-			$this->publishActivity(
296
-				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
297
-				[$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
298
-				$share->getSharedBy(),
299
-				$share->getNode()->getId(),
300
-				$userFolder->getRelativePath($share->getNode()->getPath())
301
-			);
302
-		}
303
-	}
304
-
305
-
306
-	/**
307
-	 * publish activity if a file/folder was shared by mail
308
-	 *
309
-	 * @param $subject
310
-	 * @param $parameters
311
-	 * @param $affectedUser
312
-	 * @param $fileId
313
-	 * @param $filePath
314
-	 */
315
-	protected function publishActivity($subject, $parameters, $affectedUser, $fileId, $filePath) {
316
-		$event = $this->activityManager->generateEvent();
317
-		$event->setApp('sharebymail')
318
-			->setType('shared')
319
-			->setSubject($subject, $parameters)
320
-			->setAffectedUser($affectedUser)
321
-			->setObject('files', $fileId, $filePath);
322
-		$this->activityManager->publish($event);
323
-
324
-	}
325
-
326
-	/**
327
-	 * @param IShare $share
328
-	 * @return int
329
-	 * @throws \Exception
330
-	 */
331
-	protected function createMailShare(IShare $share) {
332
-		$share->setToken($this->generateToken());
333
-		$shareId = $this->addShareToDB(
334
-			$share->getNodeId(),
335
-			$share->getNodeType(),
336
-			$share->getSharedWith(),
337
-			$share->getSharedBy(),
338
-			$share->getShareOwner(),
339
-			$share->getPermissions(),
340
-			$share->getToken(),
341
-			$share->getPassword(),
342
-			$share->getSendPasswordByTalk()
343
-		);
344
-
345
-		try {
346
-			$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
347
-				['token' => $share->getToken()]);
348
-			$this->sendMailNotification(
349
-				$share->getNode()->getName(),
350
-				$link,
351
-				$share->getSharedBy(),
352
-				$share->getSharedWith(),
353
-				$share->getExpirationDate()
354
-			);
355
-		} catch (HintException $hintException) {
356
-			$this->logger->logException($hintException, [
357
-				'message' => 'Failed to send share by mail.',
358
-				'level' => ILogger::ERROR,
359
-				'app' => 'sharebymail',
360
-			]);
361
-			$this->removeShareFromTable($shareId);
362
-			throw $hintException;
363
-		} catch (\Exception $e) {
364
-			$this->logger->logException($e, [
365
-				'message' => 'Failed to send share by mail.',
366
-				'level' => ILogger::ERROR,
367
-				'app' => 'sharebymail',
368
-			]);
369
-			$this->removeShareFromTable($shareId);
370
-			throw new HintException('Failed to send share by mail',
371
-				$this->l->t('Failed to send share by email'));
372
-		}
373
-
374
-		return $shareId;
375
-
376
-	}
377
-
378
-	/**
379
-	 * @param string $filename
380
-	 * @param string $link
381
-	 * @param string $initiator
382
-	 * @param string $shareWith
383
-	 * @param \DateTime|null $expiration
384
-	 * @throws \Exception If mail couldn't be sent
385
-	 */
386
-	protected function sendMailNotification($filename,
387
-											$link,
388
-											$initiator,
389
-											$shareWith,
390
-											\DateTime $expiration = null) {
391
-		$initiatorUser = $this->userManager->get($initiator);
392
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
393
-		$message = $this->mailer->createMessage();
394
-
395
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [
396
-			'filename' => $filename,
397
-			'link' => $link,
398
-			'initiator' => $initiatorDisplayName,
399
-			'expiration' => $expiration,
400
-			'shareWith' => $shareWith,
401
-		]);
402
-
403
-		$emailTemplate->setSubject($this->l->t('%1$s shared »%2$s« with you', array($initiatorDisplayName, $filename)));
404
-		$emailTemplate->addHeader();
405
-		$emailTemplate->addHeading($this->l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
406
-		$text = $this->l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
407
-
408
-		$emailTemplate->addBodyText(
409
-			htmlspecialchars($text . ' ' . $this->l->t('Click the button below to open it.')),
410
-			$text
411
-		);
412
-		$emailTemplate->addBodyButton(
413
-			$this->l->t('Open »%s«', [$filename]),
414
-			$link
415
-		);
416
-
417
-		$message->setTo([$shareWith]);
418
-
419
-		// The "From" contains the sharers name
420
-		$instanceName = $this->defaults->getName();
421
-		$senderName = $this->l->t(
422
-			'%1$s via %2$s',
423
-			[
424
-				$initiatorDisplayName,
425
-				$instanceName
426
-			]
427
-		);
428
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
429
-
430
-		// The "Reply-To" is set to the sharer if an mail address is configured
431
-		// also the default footer contains a "Do not reply" which needs to be adjusted.
432
-		$initiatorEmail = $initiatorUser->getEMailAddress();
433
-		if($initiatorEmail !== null) {
434
-			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
435
-			$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
436
-		} else {
437
-			$emailTemplate->addFooter();
438
-		}
439
-
440
-		$message->useTemplate($emailTemplate);
441
-		$this->mailer->send($message);
442
-	}
443
-
444
-	/**
445
-	 * send password to recipient of a mail share
446
-	 *
447
-	 * @param IShare $share
448
-	 * @param string $password
449
-	 * @return bool
450
-	 */
451
-	protected function sendPassword(IShare $share, $password) {
452
-
453
-		$filename = $share->getNode()->getName();
454
-		$initiator = $share->getSharedBy();
455
-		$shareWith = $share->getSharedWith();
456
-
457
-		if ($password === '' || $this->settingsManager->sendPasswordByMail() === false || $share->getSendPasswordByTalk()) {
458
-			return false;
459
-		}
460
-
461
-		$initiatorUser = $this->userManager->get($initiator);
462
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
463
-		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
464
-
465
-		$plainBodyPart = $this->l->t("%1\$s shared »%2\$s« with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]);
466
-		$htmlBodyPart = $this->l->t('%1$s shared »%2$s« with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
467
-
468
-		$message = $this->mailer->createMessage();
469
-
470
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [
471
-			'filename' => $filename,
472
-			'password' => $password,
473
-			'initiator' => $initiatorDisplayName,
474
-			'initiatorEmail' => $initiatorEmailAddress,
475
-			'shareWith' => $shareWith,
476
-		]);
477
-
478
-		$emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared to you by %2$s', [$filename, $initiatorDisplayName]));
479
-		$emailTemplate->addHeader();
480
-		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
481
-		$emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart);
482
-		$emailTemplate->addBodyText($this->l->t('It is protected with the following password:'));
483
-		$emailTemplate->addBodyText($password);
484
-
485
-		// The "From" contains the sharers name
486
-		$instanceName = $this->defaults->getName();
487
-		$senderName = $this->l->t(
488
-			'%1$s via %2$s',
489
-			[
490
-				$initiatorDisplayName,
491
-				$instanceName
492
-			]
493
-		);
494
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
495
-		if ($initiatorEmailAddress !== null) {
496
-			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
497
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
498
-		} else {
499
-			$emailTemplate->addFooter();
500
-		}
501
-
502
-		$message->setTo([$shareWith]);
503
-		$message->useTemplate($emailTemplate);
504
-		$this->mailer->send($message);
505
-
506
-		$this->createPasswordSendActivity($share, $shareWith, false);
507
-
508
-		return true;
509
-	}
510
-
511
-	protected function sendNote(IShare $share) {
512
-
513
-		$recipient = $share->getSharedWith();
514
-
515
-
516
-		$filename = $share->getNode()->getName();
517
-		$initiator = $share->getSharedBy();
518
-		$note = $share->getNote();
519
-
520
-		$initiatorUser = $this->userManager->get($initiator);
521
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
522
-		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
523
-
524
-		$plainHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
525
-		$htmlHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
526
-
527
-		$message = $this->mailer->createMessage();
528
-
529
-		$emailTemplate = $this->mailer->createEMailTemplate('shareByMail.sendNote');
530
-
531
-		$emailTemplate->setSubject($this->l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
532
-		$emailTemplate->addHeader();
533
-		$emailTemplate->addHeading(htmlspecialchars($htmlHeading), $plainHeading);
534
-		$emailTemplate->addBodyText(htmlspecialchars($note), $note);
535
-
536
-		$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
537
-			['token' => $share->getToken()]);
538
-		$emailTemplate->addBodyButton(
539
-			$this->l->t('Open »%s«', [$filename]),
540
-			$link
541
-		);
542
-
543
-		// The "From" contains the sharers name
544
-		$instanceName = $this->defaults->getName();
545
-		$senderName = $this->l->t(
546
-			'%1$s via %2$s',
547
-			[
548
-				$initiatorDisplayName,
549
-				$instanceName
550
-			]
551
-		);
552
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
553
-		if ($initiatorEmailAddress !== null) {
554
-			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
555
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
556
-		} else {
557
-			$emailTemplate->addFooter();
558
-		}
559
-
560
-		$message->setTo([$recipient]);
561
-		$message->useTemplate($emailTemplate);
562
-		$this->mailer->send($message);
563
-
564
-	}
565
-
566
-	/**
567
-	 * send auto generated password to the owner. This happens if the admin enforces
568
-	 * a password for mail shares and forbid to send the password by mail to the recipient
569
-	 *
570
-	 * @param IShare $share
571
-	 * @param string $password
572
-	 * @return bool
573
-	 * @throws \Exception
574
-	 */
575
-	protected function sendPasswordToOwner(IShare $share, $password) {
576
-
577
-		$filename = $share->getNode()->getName();
578
-		$initiator = $this->userManager->get($share->getSharedBy());
579
-		$initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
580
-		$initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
581
-		$shareWith = $share->getSharedWith();
582
-
583
-		if ($initiatorEMailAddress === null) {
584
-			throw new \Exception(
585
-				$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.")
586
-			);
587
-		}
588
-
589
-		$bodyPart = $this->l->t('You just shared »%1$s« with %2$s. The share was already send to the recipient. Due to the security policies defined by the administrator of %3$s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient.', [$filename, $shareWith, $this->defaults->getName()]);
590
-
591
-		$message = $this->mailer->createMessage();
592
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [
593
-			'filename' => $filename,
594
-			'password' => $password,
595
-			'initiator' => $initiatorDisplayName,
596
-			'initiatorEmail' => $initiatorEMailAddress,
597
-			'shareWith' => $shareWith,
598
-		]);
599
-
600
-		$emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared with %2$s', [$filename, $shareWith]));
601
-		$emailTemplate->addHeader();
602
-		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
603
-		$emailTemplate->addBodyText($bodyPart);
604
-		$emailTemplate->addBodyText($this->l->t('This is the password:'));
605
-		$emailTemplate->addBodyText($password);
606
-		$emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
607
-		$emailTemplate->addFooter();
608
-
609
-		if ($initiatorEMailAddress) {
610
-			$message->setFrom([$initiatorEMailAddress => $initiatorDisplayName]);
611
-		}
612
-		$message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
613
-		$message->useTemplate($emailTemplate);
614
-		$this->mailer->send($message);
615
-
616
-		$this->createPasswordSendActivity($share, $shareWith, true);
617
-
618
-		return true;
619
-	}
620
-
621
-	/**
622
-	 * generate share token
623
-	 *
624
-	 * @return string
625
-	 */
626
-	protected function generateToken($size = 15) {
627
-		$token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
628
-		return $token;
629
-	}
630
-
631
-	/**
632
-	 * Get all children of this share
633
-	 *
634
-	 * @param IShare $parent
635
-	 * @return IShare[]
636
-	 */
637
-	public function getChildren(IShare $parent) {
638
-		$children = [];
639
-
640
-		$qb = $this->dbConnection->getQueryBuilder();
641
-		$qb->select('*')
642
-			->from('share')
643
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
644
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
645
-			->orderBy('id');
646
-
647
-		$cursor = $qb->execute();
648
-		while($data = $cursor->fetch()) {
649
-			$children[] = $this->createShareObject($data);
650
-		}
651
-		$cursor->closeCursor();
652
-
653
-		return $children;
654
-	}
655
-
656
-	/**
657
-	 * add share to the database and return the ID
658
-	 *
659
-	 * @param int $itemSource
660
-	 * @param string $itemType
661
-	 * @param string $shareWith
662
-	 * @param string $sharedBy
663
-	 * @param string $uidOwner
664
-	 * @param int $permissions
665
-	 * @param string $token
666
-	 * @param string $password
667
-	 * @param bool $sendPasswordByTalk
668
-	 * @return int
669
-	 */
670
-	protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password, $sendPasswordByTalk) {
671
-		$qb = $this->dbConnection->getQueryBuilder();
672
-		$qb->insert('share')
673
-			->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
674
-			->setValue('item_type', $qb->createNamedParameter($itemType))
675
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
676
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
677
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
678
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
679
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
680
-			->setValue('permissions', $qb->createNamedParameter($permissions))
681
-			->setValue('token', $qb->createNamedParameter($token))
682
-			->setValue('password', $qb->createNamedParameter($password))
683
-			->setValue('password_by_talk', $qb->createNamedParameter($sendPasswordByTalk, IQueryBuilder::PARAM_BOOL))
684
-			->setValue('stime', $qb->createNamedParameter(time()));
685
-
686
-		/*
166
+        $alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_EMAIL, $share->getNode(), 1, 0);
167
+        if (!empty($alreadyShared)) {
168
+            $message = 'Sharing %1$s failed, this item is already shared with %2$s';
169
+            $message_t = $this->l->t('Sharing %1$s failed, this item is already shared with %2$s', array($share->getNode()->getName(), $shareWith));
170
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
171
+            throw new \Exception($message_t);
172
+        }
173
+
174
+        // if the admin enforces a password for all mail shares we create a
175
+        // random password and send it to the recipient
176
+        $password = '';
177
+        $passwordEnforced = $this->settingsManager->enforcePasswordProtection();
178
+        if ($passwordEnforced) {
179
+            $password = $this->autoGeneratePassword($share);
180
+        }
181
+
182
+        $shareId = $this->createMailShare($share);
183
+        $send = $this->sendPassword($share, $password);
184
+        if ($passwordEnforced && $send === false) {
185
+            $this->sendPasswordToOwner($share, $password);
186
+        }
187
+
188
+        $this->createShareActivity($share);
189
+        $data = $this->getRawShare($shareId);
190
+
191
+        return $this->createShareObject($data);
192
+
193
+    }
194
+
195
+    /**
196
+     * auto generate password in case of password enforcement on mail shares
197
+     *
198
+     * @param IShare $share
199
+     * @return string
200
+     * @throws \Exception
201
+     */
202
+    protected function autoGeneratePassword($share) {
203
+        $initiatorUser = $this->userManager->get($share->getSharedBy());
204
+        $initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
205
+        $allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
206
+
207
+        if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
208
+            throw new \Exception(
209
+                $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.")
210
+            );
211
+        }
212
+
213
+        $passwordPolicy = $this->getPasswordPolicy();
214
+        $passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS;
215
+        $passwordLength = 8;
216
+        if (!empty($passwordPolicy)) {
217
+            $passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength;
218
+            $passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : '';
219
+        }
220
+
221
+        $password = $this->secureRandom->generate($passwordLength, $passwordCharset);
222
+
223
+        $share->setPassword($this->hasher->hash($password));
224
+
225
+        return $password;
226
+    }
227
+
228
+    /**
229
+     * get password policy
230
+     *
231
+     * @return array
232
+     */
233
+    protected function getPasswordPolicy() {
234
+        $capabilities = $this->capabilitiesManager->getCapabilities();
235
+        if (isset($capabilities['password_policy'])) {
236
+            return $capabilities['password_policy'];
237
+        }
238
+
239
+        return [];
240
+    }
241
+
242
+    /**
243
+     * create activity if a file/folder was shared by mail
244
+     *
245
+     * @param IShare $share
246
+     */
247
+    protected function createShareActivity(IShare $share) {
248
+
249
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
250
+
251
+        $this->publishActivity(
252
+            Activity::SUBJECT_SHARED_EMAIL_SELF,
253
+            [$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
254
+            $share->getSharedBy(),
255
+            $share->getNode()->getId(),
256
+            $userFolder->getRelativePath($share->getNode()->getPath())
257
+        );
258
+
259
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
260
+            $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
261
+            $fileId = $share->getNode()->getId();
262
+            $nodes = $ownerFolder->getById($fileId);
263
+            $ownerPath = $nodes[0]->getPath();
264
+            $this->publishActivity(
265
+                Activity::SUBJECT_SHARED_EMAIL_BY,
266
+                [$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
267
+                $share->getShareOwner(),
268
+                $fileId,
269
+                $ownerFolder->getRelativePath($ownerPath)
270
+            );
271
+        }
272
+
273
+    }
274
+
275
+    /**
276
+     * create activity if a file/folder was shared by mail
277
+     *
278
+     * @param IShare $share
279
+     * @param string $sharedWith
280
+     * @param bool $sendToSelf
281
+     */
282
+    protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) {
283
+
284
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
285
+
286
+        if ($sendToSelf) {
287
+            $this->publishActivity(
288
+                Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
289
+                [$userFolder->getRelativePath($share->getNode()->getPath())],
290
+                $share->getSharedBy(),
291
+                $share->getNode()->getId(),
292
+                $userFolder->getRelativePath($share->getNode()->getPath())
293
+            );
294
+        } else {
295
+            $this->publishActivity(
296
+                Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
297
+                [$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
298
+                $share->getSharedBy(),
299
+                $share->getNode()->getId(),
300
+                $userFolder->getRelativePath($share->getNode()->getPath())
301
+            );
302
+        }
303
+    }
304
+
305
+
306
+    /**
307
+     * publish activity if a file/folder was shared by mail
308
+     *
309
+     * @param $subject
310
+     * @param $parameters
311
+     * @param $affectedUser
312
+     * @param $fileId
313
+     * @param $filePath
314
+     */
315
+    protected function publishActivity($subject, $parameters, $affectedUser, $fileId, $filePath) {
316
+        $event = $this->activityManager->generateEvent();
317
+        $event->setApp('sharebymail')
318
+            ->setType('shared')
319
+            ->setSubject($subject, $parameters)
320
+            ->setAffectedUser($affectedUser)
321
+            ->setObject('files', $fileId, $filePath);
322
+        $this->activityManager->publish($event);
323
+
324
+    }
325
+
326
+    /**
327
+     * @param IShare $share
328
+     * @return int
329
+     * @throws \Exception
330
+     */
331
+    protected function createMailShare(IShare $share) {
332
+        $share->setToken($this->generateToken());
333
+        $shareId = $this->addShareToDB(
334
+            $share->getNodeId(),
335
+            $share->getNodeType(),
336
+            $share->getSharedWith(),
337
+            $share->getSharedBy(),
338
+            $share->getShareOwner(),
339
+            $share->getPermissions(),
340
+            $share->getToken(),
341
+            $share->getPassword(),
342
+            $share->getSendPasswordByTalk()
343
+        );
344
+
345
+        try {
346
+            $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
347
+                ['token' => $share->getToken()]);
348
+            $this->sendMailNotification(
349
+                $share->getNode()->getName(),
350
+                $link,
351
+                $share->getSharedBy(),
352
+                $share->getSharedWith(),
353
+                $share->getExpirationDate()
354
+            );
355
+        } catch (HintException $hintException) {
356
+            $this->logger->logException($hintException, [
357
+                'message' => 'Failed to send share by mail.',
358
+                'level' => ILogger::ERROR,
359
+                'app' => 'sharebymail',
360
+            ]);
361
+            $this->removeShareFromTable($shareId);
362
+            throw $hintException;
363
+        } catch (\Exception $e) {
364
+            $this->logger->logException($e, [
365
+                'message' => 'Failed to send share by mail.',
366
+                'level' => ILogger::ERROR,
367
+                'app' => 'sharebymail',
368
+            ]);
369
+            $this->removeShareFromTable($shareId);
370
+            throw new HintException('Failed to send share by mail',
371
+                $this->l->t('Failed to send share by email'));
372
+        }
373
+
374
+        return $shareId;
375
+
376
+    }
377
+
378
+    /**
379
+     * @param string $filename
380
+     * @param string $link
381
+     * @param string $initiator
382
+     * @param string $shareWith
383
+     * @param \DateTime|null $expiration
384
+     * @throws \Exception If mail couldn't be sent
385
+     */
386
+    protected function sendMailNotification($filename,
387
+                                            $link,
388
+                                            $initiator,
389
+                                            $shareWith,
390
+                                            \DateTime $expiration = null) {
391
+        $initiatorUser = $this->userManager->get($initiator);
392
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
393
+        $message = $this->mailer->createMessage();
394
+
395
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [
396
+            'filename' => $filename,
397
+            'link' => $link,
398
+            'initiator' => $initiatorDisplayName,
399
+            'expiration' => $expiration,
400
+            'shareWith' => $shareWith,
401
+        ]);
402
+
403
+        $emailTemplate->setSubject($this->l->t('%1$s shared »%2$s« with you', array($initiatorDisplayName, $filename)));
404
+        $emailTemplate->addHeader();
405
+        $emailTemplate->addHeading($this->l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
406
+        $text = $this->l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
407
+
408
+        $emailTemplate->addBodyText(
409
+            htmlspecialchars($text . ' ' . $this->l->t('Click the button below to open it.')),
410
+            $text
411
+        );
412
+        $emailTemplate->addBodyButton(
413
+            $this->l->t('Open »%s«', [$filename]),
414
+            $link
415
+        );
416
+
417
+        $message->setTo([$shareWith]);
418
+
419
+        // The "From" contains the sharers name
420
+        $instanceName = $this->defaults->getName();
421
+        $senderName = $this->l->t(
422
+            '%1$s via %2$s',
423
+            [
424
+                $initiatorDisplayName,
425
+                $instanceName
426
+            ]
427
+        );
428
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
429
+
430
+        // The "Reply-To" is set to the sharer if an mail address is configured
431
+        // also the default footer contains a "Do not reply" which needs to be adjusted.
432
+        $initiatorEmail = $initiatorUser->getEMailAddress();
433
+        if($initiatorEmail !== null) {
434
+            $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
435
+            $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
436
+        } else {
437
+            $emailTemplate->addFooter();
438
+        }
439
+
440
+        $message->useTemplate($emailTemplate);
441
+        $this->mailer->send($message);
442
+    }
443
+
444
+    /**
445
+     * send password to recipient of a mail share
446
+     *
447
+     * @param IShare $share
448
+     * @param string $password
449
+     * @return bool
450
+     */
451
+    protected function sendPassword(IShare $share, $password) {
452
+
453
+        $filename = $share->getNode()->getName();
454
+        $initiator = $share->getSharedBy();
455
+        $shareWith = $share->getSharedWith();
456
+
457
+        if ($password === '' || $this->settingsManager->sendPasswordByMail() === false || $share->getSendPasswordByTalk()) {
458
+            return false;
459
+        }
460
+
461
+        $initiatorUser = $this->userManager->get($initiator);
462
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
463
+        $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
464
+
465
+        $plainBodyPart = $this->l->t("%1\$s shared »%2\$s« with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]);
466
+        $htmlBodyPart = $this->l->t('%1$s shared »%2$s« with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
467
+
468
+        $message = $this->mailer->createMessage();
469
+
470
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [
471
+            'filename' => $filename,
472
+            'password' => $password,
473
+            'initiator' => $initiatorDisplayName,
474
+            'initiatorEmail' => $initiatorEmailAddress,
475
+            'shareWith' => $shareWith,
476
+        ]);
477
+
478
+        $emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared to you by %2$s', [$filename, $initiatorDisplayName]));
479
+        $emailTemplate->addHeader();
480
+        $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
481
+        $emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart);
482
+        $emailTemplate->addBodyText($this->l->t('It is protected with the following password:'));
483
+        $emailTemplate->addBodyText($password);
484
+
485
+        // The "From" contains the sharers name
486
+        $instanceName = $this->defaults->getName();
487
+        $senderName = $this->l->t(
488
+            '%1$s via %2$s',
489
+            [
490
+                $initiatorDisplayName,
491
+                $instanceName
492
+            ]
493
+        );
494
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
495
+        if ($initiatorEmailAddress !== null) {
496
+            $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
497
+            $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
498
+        } else {
499
+            $emailTemplate->addFooter();
500
+        }
501
+
502
+        $message->setTo([$shareWith]);
503
+        $message->useTemplate($emailTemplate);
504
+        $this->mailer->send($message);
505
+
506
+        $this->createPasswordSendActivity($share, $shareWith, false);
507
+
508
+        return true;
509
+    }
510
+
511
+    protected function sendNote(IShare $share) {
512
+
513
+        $recipient = $share->getSharedWith();
514
+
515
+
516
+        $filename = $share->getNode()->getName();
517
+        $initiator = $share->getSharedBy();
518
+        $note = $share->getNote();
519
+
520
+        $initiatorUser = $this->userManager->get($initiator);
521
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
522
+        $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
523
+
524
+        $plainHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
525
+        $htmlHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
526
+
527
+        $message = $this->mailer->createMessage();
528
+
529
+        $emailTemplate = $this->mailer->createEMailTemplate('shareByMail.sendNote');
530
+
531
+        $emailTemplate->setSubject($this->l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
532
+        $emailTemplate->addHeader();
533
+        $emailTemplate->addHeading(htmlspecialchars($htmlHeading), $plainHeading);
534
+        $emailTemplate->addBodyText(htmlspecialchars($note), $note);
535
+
536
+        $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
537
+            ['token' => $share->getToken()]);
538
+        $emailTemplate->addBodyButton(
539
+            $this->l->t('Open »%s«', [$filename]),
540
+            $link
541
+        );
542
+
543
+        // The "From" contains the sharers name
544
+        $instanceName = $this->defaults->getName();
545
+        $senderName = $this->l->t(
546
+            '%1$s via %2$s',
547
+            [
548
+                $initiatorDisplayName,
549
+                $instanceName
550
+            ]
551
+        );
552
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
553
+        if ($initiatorEmailAddress !== null) {
554
+            $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
555
+            $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
556
+        } else {
557
+            $emailTemplate->addFooter();
558
+        }
559
+
560
+        $message->setTo([$recipient]);
561
+        $message->useTemplate($emailTemplate);
562
+        $this->mailer->send($message);
563
+
564
+    }
565
+
566
+    /**
567
+     * send auto generated password to the owner. This happens if the admin enforces
568
+     * a password for mail shares and forbid to send the password by mail to the recipient
569
+     *
570
+     * @param IShare $share
571
+     * @param string $password
572
+     * @return bool
573
+     * @throws \Exception
574
+     */
575
+    protected function sendPasswordToOwner(IShare $share, $password) {
576
+
577
+        $filename = $share->getNode()->getName();
578
+        $initiator = $this->userManager->get($share->getSharedBy());
579
+        $initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
580
+        $initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
581
+        $shareWith = $share->getSharedWith();
582
+
583
+        if ($initiatorEMailAddress === null) {
584
+            throw new \Exception(
585
+                $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.")
586
+            );
587
+        }
588
+
589
+        $bodyPart = $this->l->t('You just shared »%1$s« with %2$s. The share was already send to the recipient. Due to the security policies defined by the administrator of %3$s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient.', [$filename, $shareWith, $this->defaults->getName()]);
590
+
591
+        $message = $this->mailer->createMessage();
592
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [
593
+            'filename' => $filename,
594
+            'password' => $password,
595
+            'initiator' => $initiatorDisplayName,
596
+            'initiatorEmail' => $initiatorEMailAddress,
597
+            'shareWith' => $shareWith,
598
+        ]);
599
+
600
+        $emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared with %2$s', [$filename, $shareWith]));
601
+        $emailTemplate->addHeader();
602
+        $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
603
+        $emailTemplate->addBodyText($bodyPart);
604
+        $emailTemplate->addBodyText($this->l->t('This is the password:'));
605
+        $emailTemplate->addBodyText($password);
606
+        $emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
607
+        $emailTemplate->addFooter();
608
+
609
+        if ($initiatorEMailAddress) {
610
+            $message->setFrom([$initiatorEMailAddress => $initiatorDisplayName]);
611
+        }
612
+        $message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
613
+        $message->useTemplate($emailTemplate);
614
+        $this->mailer->send($message);
615
+
616
+        $this->createPasswordSendActivity($share, $shareWith, true);
617
+
618
+        return true;
619
+    }
620
+
621
+    /**
622
+     * generate share token
623
+     *
624
+     * @return string
625
+     */
626
+    protected function generateToken($size = 15) {
627
+        $token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
628
+        return $token;
629
+    }
630
+
631
+    /**
632
+     * Get all children of this share
633
+     *
634
+     * @param IShare $parent
635
+     * @return IShare[]
636
+     */
637
+    public function getChildren(IShare $parent) {
638
+        $children = [];
639
+
640
+        $qb = $this->dbConnection->getQueryBuilder();
641
+        $qb->select('*')
642
+            ->from('share')
643
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
644
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
645
+            ->orderBy('id');
646
+
647
+        $cursor = $qb->execute();
648
+        while($data = $cursor->fetch()) {
649
+            $children[] = $this->createShareObject($data);
650
+        }
651
+        $cursor->closeCursor();
652
+
653
+        return $children;
654
+    }
655
+
656
+    /**
657
+     * add share to the database and return the ID
658
+     *
659
+     * @param int $itemSource
660
+     * @param string $itemType
661
+     * @param string $shareWith
662
+     * @param string $sharedBy
663
+     * @param string $uidOwner
664
+     * @param int $permissions
665
+     * @param string $token
666
+     * @param string $password
667
+     * @param bool $sendPasswordByTalk
668
+     * @return int
669
+     */
670
+    protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password, $sendPasswordByTalk) {
671
+        $qb = $this->dbConnection->getQueryBuilder();
672
+        $qb->insert('share')
673
+            ->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
674
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
675
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
676
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
677
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
678
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
679
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
680
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
681
+            ->setValue('token', $qb->createNamedParameter($token))
682
+            ->setValue('password', $qb->createNamedParameter($password))
683
+            ->setValue('password_by_talk', $qb->createNamedParameter($sendPasswordByTalk, IQueryBuilder::PARAM_BOOL))
684
+            ->setValue('stime', $qb->createNamedParameter(time()));
685
+
686
+        /*
687 687
 		 * Added to fix https://github.com/owncloud/core/issues/22215
688 688
 		 * Can be removed once we get rid of ajax/share.php
689 689
 		 */
690
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
690
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
691 691
 
692
-		$qb->execute();
693
-		$id = $qb->getLastInsertId();
692
+        $qb->execute();
693
+        $id = $qb->getLastInsertId();
694 694
 
695
-		return (int)$id;
696
-	}
695
+        return (int)$id;
696
+    }
697 697
 
698
-	/**
699
-	 * Update a share
700
-	 *
701
-	 * @param IShare $share
702
-	 * @param string|null $plainTextPassword
703
-	 * @return IShare The share object
704
-	 */
705
-	public function update(IShare $share, $plainTextPassword = null) {
698
+    /**
699
+     * Update a share
700
+     *
701
+     * @param IShare $share
702
+     * @param string|null $plainTextPassword
703
+     * @return IShare The share object
704
+     */
705
+    public function update(IShare $share, $plainTextPassword = null) {
706 706
 
707
-		$originalShare = $this->getShareById($share->getId());
707
+        $originalShare = $this->getShareById($share->getId());
708 708
 
709
-		// a real password was given
710
-		$validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
709
+        // a real password was given
710
+        $validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
711 711
 
712
-		if($validPassword && ($originalShare->getPassword() !== $share->getPassword() ||
713
-								($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()))) {
714
-			$this->sendPassword($share, $plainTextPassword);
715
-		}
716
-		/*
712
+        if($validPassword && ($originalShare->getPassword() !== $share->getPassword() ||
713
+                                ($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()))) {
714
+            $this->sendPassword($share, $plainTextPassword);
715
+        }
716
+        /*
717 717
 		 * We allow updating the permissions and password of mail shares
718 718
 		 */
719
-		$qb = $this->dbConnection->getQueryBuilder();
720
-		$qb->update('share')
721
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
722
-			->set('permissions', $qb->createNamedParameter($share->getPermissions()))
723
-			->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
724
-			->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
725
-			->set('password', $qb->createNamedParameter($share->getPassword()))
726
-			->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
727
-			->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
728
-			->set('note', $qb->createNamedParameter($share->getNote()))
729
-			->execute();
730
-
731
-		if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
732
-			$this->sendNote($share);
733
-		}
734
-
735
-		return $share;
736
-	}
737
-
738
-	/**
739
-	 * @inheritdoc
740
-	 */
741
-	public function move(IShare $share, $recipient) {
742
-		/**
743
-		 * nothing to do here, mail shares are only outgoing shares
744
-		 */
745
-		return $share;
746
-	}
747
-
748
-	/**
749
-	 * Delete a share (owner unShares the file)
750
-	 *
751
-	 * @param IShare $share
752
-	 */
753
-	public function delete(IShare $share) {
754
-		$this->removeShareFromTable($share->getId());
755
-	}
756
-
757
-	/**
758
-	 * @inheritdoc
759
-	 */
760
-	public function deleteFromSelf(IShare $share, $recipient) {
761
-		// nothing to do here, mail shares are only outgoing shares
762
-	}
763
-
764
-	public function restore(IShare $share, string $recipient): IShare {
765
-		throw new GenericShareException('not implemented');
766
-	}
767
-
768
-	/**
769
-	 * @inheritdoc
770
-	 */
771
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
772
-		$qb = $this->dbConnection->getQueryBuilder();
773
-		$qb->select('*')
774
-			->from('share');
775
-
776
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
777
-
778
-		/**
779
-		 * Reshares for this user are shares where they are the owner.
780
-		 */
781
-		if ($reshares === false) {
782
-			//Special case for old shares created via the web UI
783
-			$or1 = $qb->expr()->andX(
784
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
785
-				$qb->expr()->isNull('uid_initiator')
786
-			);
787
-
788
-			$qb->andWhere(
789
-				$qb->expr()->orX(
790
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
791
-					$or1
792
-				)
793
-			);
794
-		} else {
795
-			$qb->andWhere(
796
-				$qb->expr()->orX(
797
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
798
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
799
-				)
800
-			);
801
-		}
802
-
803
-		if ($node !== null) {
804
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
805
-		}
806
-
807
-		if ($limit !== -1) {
808
-			$qb->setMaxResults($limit);
809
-		}
810
-
811
-		$qb->setFirstResult($offset);
812
-		$qb->orderBy('id');
813
-
814
-		$cursor = $qb->execute();
815
-		$shares = [];
816
-		while($data = $cursor->fetch()) {
817
-			$shares[] = $this->createShareObject($data);
818
-		}
819
-		$cursor->closeCursor();
820
-
821
-		return $shares;
822
-	}
823
-
824
-	/**
825
-	 * @inheritdoc
826
-	 */
827
-	public function getShareById($id, $recipientId = null) {
828
-		$qb = $this->dbConnection->getQueryBuilder();
829
-
830
-		$qb->select('*')
831
-			->from('share')
832
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
833
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
834
-
835
-		$cursor = $qb->execute();
836
-		$data = $cursor->fetch();
837
-		$cursor->closeCursor();
838
-
839
-		if ($data === false) {
840
-			throw new ShareNotFound();
841
-		}
842
-
843
-		try {
844
-			$share = $this->createShareObject($data);
845
-		} catch (InvalidShare $e) {
846
-			throw new ShareNotFound();
847
-		}
848
-
849
-		return $share;
850
-	}
851
-
852
-	/**
853
-	 * Get shares for a given path
854
-	 *
855
-	 * @param \OCP\Files\Node $path
856
-	 * @return IShare[]
857
-	 */
858
-	public function getSharesByPath(Node $path) {
859
-		$qb = $this->dbConnection->getQueryBuilder();
860
-
861
-		$cursor = $qb->select('*')
862
-			->from('share')
863
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
864
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
865
-			->execute();
866
-
867
-		$shares = [];
868
-		while($data = $cursor->fetch()) {
869
-			$shares[] = $this->createShareObject($data);
870
-		}
871
-		$cursor->closeCursor();
872
-
873
-		return $shares;
874
-	}
875
-
876
-	/**
877
-	 * @inheritdoc
878
-	 */
879
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
880
-		/** @var IShare[] $shares */
881
-		$shares = [];
882
-
883
-		//Get shares directly with this user
884
-		$qb = $this->dbConnection->getQueryBuilder();
885
-		$qb->select('*')
886
-			->from('share');
887
-
888
-		// Order by id
889
-		$qb->orderBy('id');
890
-
891
-		// Set limit and offset
892
-		if ($limit !== -1) {
893
-			$qb->setMaxResults($limit);
894
-		}
895
-		$qb->setFirstResult($offset);
896
-
897
-		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
898
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
899
-
900
-		// Filter by node if provided
901
-		if ($node !== null) {
902
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
903
-		}
904
-
905
-		$cursor = $qb->execute();
906
-
907
-		while($data = $cursor->fetch()) {
908
-			$shares[] = $this->createShareObject($data);
909
-		}
910
-		$cursor->closeCursor();
911
-
912
-
913
-		return $shares;
914
-	}
915
-
916
-	/**
917
-	 * Get a share by token
918
-	 *
919
-	 * @param string $token
920
-	 * @return IShare
921
-	 * @throws ShareNotFound
922
-	 */
923
-	public function getShareByToken($token) {
924
-		$qb = $this->dbConnection->getQueryBuilder();
925
-
926
-		$cursor = $qb->select('*')
927
-			->from('share')
928
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
929
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
930
-			->execute();
931
-
932
-		$data = $cursor->fetch();
933
-
934
-		if ($data === false) {
935
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
936
-		}
937
-
938
-		try {
939
-			$share = $this->createShareObject($data);
940
-		} catch (InvalidShare $e) {
941
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
942
-		}
943
-
944
-		return $share;
945
-	}
946
-
947
-	/**
948
-	 * remove share from table
949
-	 *
950
-	 * @param string $shareId
951
-	 */
952
-	protected function removeShareFromTable($shareId) {
953
-		$qb = $this->dbConnection->getQueryBuilder();
954
-		$qb->delete('share')
955
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
956
-		$qb->execute();
957
-	}
958
-
959
-	/**
960
-	 * Create a share object from an database row
961
-	 *
962
-	 * @param array $data
963
-	 * @return IShare
964
-	 * @throws InvalidShare
965
-	 * @throws ShareNotFound
966
-	 */
967
-	protected function createShareObject($data) {
968
-
969
-		$share = new Share($this->rootFolder, $this->userManager);
970
-		$share->setId((int)$data['id'])
971
-			->setShareType((int)$data['share_type'])
972
-			->setPermissions((int)$data['permissions'])
973
-			->setTarget($data['file_target'])
974
-			->setMailSend((bool)$data['mail_send'])
975
-			->setNote($data['note'])
976
-			->setToken($data['token']);
977
-
978
-		$shareTime = new \DateTime();
979
-		$shareTime->setTimestamp((int)$data['stime']);
980
-		$share->setShareTime($shareTime);
981
-		$share->setSharedWith($data['share_with']);
982
-		$share->setPassword($data['password']);
983
-		$share->setSendPasswordByTalk($data['password_by_talk']);
984
-
985
-		if ($data['uid_initiator'] !== null) {
986
-			$share->setShareOwner($data['uid_owner']);
987
-			$share->setSharedBy($data['uid_initiator']);
988
-		} else {
989
-			//OLD SHARE
990
-			$share->setSharedBy($data['uid_owner']);
991
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
992
-
993
-			$owner = $path->getOwner();
994
-			$share->setShareOwner($owner->getUID());
995
-		}
996
-
997
-		if ($data['expiration'] !== null) {
998
-			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
999
-			if ($expiration !== false) {
1000
-				$share->setExpirationDate($expiration);
1001
-			}
1002
-		}
1003
-
1004
-		$share->setNodeId((int)$data['file_source']);
1005
-		$share->setNodeType($data['item_type']);
1006
-
1007
-		$share->setProviderId($this->identifier());
1008
-
1009
-		return $share;
1010
-	}
1011
-
1012
-	/**
1013
-	 * Get the node with file $id for $user
1014
-	 *
1015
-	 * @param string $userId
1016
-	 * @param int $id
1017
-	 * @return \OCP\Files\File|\OCP\Files\Folder
1018
-	 * @throws InvalidShare
1019
-	 */
1020
-	private function getNode($userId, $id) {
1021
-		try {
1022
-			$userFolder = $this->rootFolder->getUserFolder($userId);
1023
-		} catch (NoUserException $e) {
1024
-			throw new InvalidShare();
1025
-		}
1026
-
1027
-		$nodes = $userFolder->getById($id);
1028
-
1029
-		if (empty($nodes)) {
1030
-			throw new InvalidShare();
1031
-		}
1032
-
1033
-		return $nodes[0];
1034
-	}
1035
-
1036
-	/**
1037
-	 * A user is deleted from the system
1038
-	 * So clean up the relevant shares.
1039
-	 *
1040
-	 * @param string $uid
1041
-	 * @param int $shareType
1042
-	 */
1043
-	public function userDeleted($uid, $shareType) {
1044
-		$qb = $this->dbConnection->getQueryBuilder();
1045
-
1046
-		$qb->delete('share')
1047
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
1048
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
1049
-			->execute();
1050
-	}
1051
-
1052
-	/**
1053
-	 * This provider does not support group shares
1054
-	 *
1055
-	 * @param string $gid
1056
-	 */
1057
-	public function groupDeleted($gid) {
1058
-	}
1059
-
1060
-	/**
1061
-	 * This provider does not support group shares
1062
-	 *
1063
-	 * @param string $uid
1064
-	 * @param string $gid
1065
-	 */
1066
-	public function userDeletedFromGroup($uid, $gid) {
1067
-	}
1068
-
1069
-	/**
1070
-	 * get database row of a give share
1071
-	 *
1072
-	 * @param $id
1073
-	 * @return array
1074
-	 * @throws ShareNotFound
1075
-	 */
1076
-	protected function getRawShare($id) {
1077
-
1078
-		// Now fetch the inserted share and create a complete share object
1079
-		$qb = $this->dbConnection->getQueryBuilder();
1080
-		$qb->select('*')
1081
-			->from('share')
1082
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1083
-
1084
-		$cursor = $qb->execute();
1085
-		$data = $cursor->fetch();
1086
-		$cursor->closeCursor();
1087
-
1088
-		if ($data === false) {
1089
-			throw new ShareNotFound;
1090
-		}
1091
-
1092
-		return $data;
1093
-	}
1094
-
1095
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
1096
-		$qb = $this->dbConnection->getQueryBuilder();
1097
-		$qb->select('*')
1098
-			->from('share', 's')
1099
-			->andWhere($qb->expr()->orX(
1100
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1101
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1102
-			))
1103
-			->andWhere(
1104
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
1105
-			);
1106
-
1107
-		/**
1108
-		 * Reshares for this user are shares where they are the owner.
1109
-		 */
1110
-		if ($reshares === false) {
1111
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1112
-		} else {
1113
-			$qb->andWhere(
1114
-				$qb->expr()->orX(
1115
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1116
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1117
-				)
1118
-			);
1119
-		}
1120
-
1121
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1122
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1123
-
1124
-		$qb->orderBy('id');
1125
-
1126
-		$cursor = $qb->execute();
1127
-		$shares = [];
1128
-		while ($data = $cursor->fetch()) {
1129
-			$shares[$data['fileid']][] = $this->createShareObject($data);
1130
-		}
1131
-		$cursor->closeCursor();
1132
-
1133
-		return $shares;
1134
-	}
1135
-
1136
-	/**
1137
-	 * @inheritdoc
1138
-	 */
1139
-	public function getAccessList($nodes, $currentAccess) {
1140
-		$ids = [];
1141
-		foreach ($nodes as $node) {
1142
-			$ids[] = $node->getId();
1143
-		}
1144
-
1145
-		$qb = $this->dbConnection->getQueryBuilder();
1146
-		$qb->select('share_with')
1147
-			->from('share')
1148
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
1149
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1150
-			->andWhere($qb->expr()->orX(
1151
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1152
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1153
-			))
1154
-			->setMaxResults(1);
1155
-		$cursor = $qb->execute();
1156
-
1157
-		$mail = $cursor->fetch() !== false;
1158
-		$cursor->closeCursor();
1159
-
1160
-		return ['public' => $mail];
1161
-	}
719
+        $qb = $this->dbConnection->getQueryBuilder();
720
+        $qb->update('share')
721
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
722
+            ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
723
+            ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
724
+            ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
725
+            ->set('password', $qb->createNamedParameter($share->getPassword()))
726
+            ->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
727
+            ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
728
+            ->set('note', $qb->createNamedParameter($share->getNote()))
729
+            ->execute();
730
+
731
+        if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
732
+            $this->sendNote($share);
733
+        }
734
+
735
+        return $share;
736
+    }
737
+
738
+    /**
739
+     * @inheritdoc
740
+     */
741
+    public function move(IShare $share, $recipient) {
742
+        /**
743
+         * nothing to do here, mail shares are only outgoing shares
744
+         */
745
+        return $share;
746
+    }
747
+
748
+    /**
749
+     * Delete a share (owner unShares the file)
750
+     *
751
+     * @param IShare $share
752
+     */
753
+    public function delete(IShare $share) {
754
+        $this->removeShareFromTable($share->getId());
755
+    }
756
+
757
+    /**
758
+     * @inheritdoc
759
+     */
760
+    public function deleteFromSelf(IShare $share, $recipient) {
761
+        // nothing to do here, mail shares are only outgoing shares
762
+    }
763
+
764
+    public function restore(IShare $share, string $recipient): IShare {
765
+        throw new GenericShareException('not implemented');
766
+    }
767
+
768
+    /**
769
+     * @inheritdoc
770
+     */
771
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
772
+        $qb = $this->dbConnection->getQueryBuilder();
773
+        $qb->select('*')
774
+            ->from('share');
775
+
776
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
777
+
778
+        /**
779
+         * Reshares for this user are shares where they are the owner.
780
+         */
781
+        if ($reshares === false) {
782
+            //Special case for old shares created via the web UI
783
+            $or1 = $qb->expr()->andX(
784
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
785
+                $qb->expr()->isNull('uid_initiator')
786
+            );
787
+
788
+            $qb->andWhere(
789
+                $qb->expr()->orX(
790
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
791
+                    $or1
792
+                )
793
+            );
794
+        } else {
795
+            $qb->andWhere(
796
+                $qb->expr()->orX(
797
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
798
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
799
+                )
800
+            );
801
+        }
802
+
803
+        if ($node !== null) {
804
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
805
+        }
806
+
807
+        if ($limit !== -1) {
808
+            $qb->setMaxResults($limit);
809
+        }
810
+
811
+        $qb->setFirstResult($offset);
812
+        $qb->orderBy('id');
813
+
814
+        $cursor = $qb->execute();
815
+        $shares = [];
816
+        while($data = $cursor->fetch()) {
817
+            $shares[] = $this->createShareObject($data);
818
+        }
819
+        $cursor->closeCursor();
820
+
821
+        return $shares;
822
+    }
823
+
824
+    /**
825
+     * @inheritdoc
826
+     */
827
+    public function getShareById($id, $recipientId = null) {
828
+        $qb = $this->dbConnection->getQueryBuilder();
829
+
830
+        $qb->select('*')
831
+            ->from('share')
832
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
833
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
834
+
835
+        $cursor = $qb->execute();
836
+        $data = $cursor->fetch();
837
+        $cursor->closeCursor();
838
+
839
+        if ($data === false) {
840
+            throw new ShareNotFound();
841
+        }
842
+
843
+        try {
844
+            $share = $this->createShareObject($data);
845
+        } catch (InvalidShare $e) {
846
+            throw new ShareNotFound();
847
+        }
848
+
849
+        return $share;
850
+    }
851
+
852
+    /**
853
+     * Get shares for a given path
854
+     *
855
+     * @param \OCP\Files\Node $path
856
+     * @return IShare[]
857
+     */
858
+    public function getSharesByPath(Node $path) {
859
+        $qb = $this->dbConnection->getQueryBuilder();
860
+
861
+        $cursor = $qb->select('*')
862
+            ->from('share')
863
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
864
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
865
+            ->execute();
866
+
867
+        $shares = [];
868
+        while($data = $cursor->fetch()) {
869
+            $shares[] = $this->createShareObject($data);
870
+        }
871
+        $cursor->closeCursor();
872
+
873
+        return $shares;
874
+    }
875
+
876
+    /**
877
+     * @inheritdoc
878
+     */
879
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
880
+        /** @var IShare[] $shares */
881
+        $shares = [];
882
+
883
+        //Get shares directly with this user
884
+        $qb = $this->dbConnection->getQueryBuilder();
885
+        $qb->select('*')
886
+            ->from('share');
887
+
888
+        // Order by id
889
+        $qb->orderBy('id');
890
+
891
+        // Set limit and offset
892
+        if ($limit !== -1) {
893
+            $qb->setMaxResults($limit);
894
+        }
895
+        $qb->setFirstResult($offset);
896
+
897
+        $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
898
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
899
+
900
+        // Filter by node if provided
901
+        if ($node !== null) {
902
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
903
+        }
904
+
905
+        $cursor = $qb->execute();
906
+
907
+        while($data = $cursor->fetch()) {
908
+            $shares[] = $this->createShareObject($data);
909
+        }
910
+        $cursor->closeCursor();
911
+
912
+
913
+        return $shares;
914
+    }
915
+
916
+    /**
917
+     * Get a share by token
918
+     *
919
+     * @param string $token
920
+     * @return IShare
921
+     * @throws ShareNotFound
922
+     */
923
+    public function getShareByToken($token) {
924
+        $qb = $this->dbConnection->getQueryBuilder();
925
+
926
+        $cursor = $qb->select('*')
927
+            ->from('share')
928
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
929
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
930
+            ->execute();
931
+
932
+        $data = $cursor->fetch();
933
+
934
+        if ($data === false) {
935
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
936
+        }
937
+
938
+        try {
939
+            $share = $this->createShareObject($data);
940
+        } catch (InvalidShare $e) {
941
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
942
+        }
943
+
944
+        return $share;
945
+    }
946
+
947
+    /**
948
+     * remove share from table
949
+     *
950
+     * @param string $shareId
951
+     */
952
+    protected function removeShareFromTable($shareId) {
953
+        $qb = $this->dbConnection->getQueryBuilder();
954
+        $qb->delete('share')
955
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
956
+        $qb->execute();
957
+    }
958
+
959
+    /**
960
+     * Create a share object from an database row
961
+     *
962
+     * @param array $data
963
+     * @return IShare
964
+     * @throws InvalidShare
965
+     * @throws ShareNotFound
966
+     */
967
+    protected function createShareObject($data) {
968
+
969
+        $share = new Share($this->rootFolder, $this->userManager);
970
+        $share->setId((int)$data['id'])
971
+            ->setShareType((int)$data['share_type'])
972
+            ->setPermissions((int)$data['permissions'])
973
+            ->setTarget($data['file_target'])
974
+            ->setMailSend((bool)$data['mail_send'])
975
+            ->setNote($data['note'])
976
+            ->setToken($data['token']);
977
+
978
+        $shareTime = new \DateTime();
979
+        $shareTime->setTimestamp((int)$data['stime']);
980
+        $share->setShareTime($shareTime);
981
+        $share->setSharedWith($data['share_with']);
982
+        $share->setPassword($data['password']);
983
+        $share->setSendPasswordByTalk($data['password_by_talk']);
984
+
985
+        if ($data['uid_initiator'] !== null) {
986
+            $share->setShareOwner($data['uid_owner']);
987
+            $share->setSharedBy($data['uid_initiator']);
988
+        } else {
989
+            //OLD SHARE
990
+            $share->setSharedBy($data['uid_owner']);
991
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
992
+
993
+            $owner = $path->getOwner();
994
+            $share->setShareOwner($owner->getUID());
995
+        }
996
+
997
+        if ($data['expiration'] !== null) {
998
+            $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
999
+            if ($expiration !== false) {
1000
+                $share->setExpirationDate($expiration);
1001
+            }
1002
+        }
1003
+
1004
+        $share->setNodeId((int)$data['file_source']);
1005
+        $share->setNodeType($data['item_type']);
1006
+
1007
+        $share->setProviderId($this->identifier());
1008
+
1009
+        return $share;
1010
+    }
1011
+
1012
+    /**
1013
+     * Get the node with file $id for $user
1014
+     *
1015
+     * @param string $userId
1016
+     * @param int $id
1017
+     * @return \OCP\Files\File|\OCP\Files\Folder
1018
+     * @throws InvalidShare
1019
+     */
1020
+    private function getNode($userId, $id) {
1021
+        try {
1022
+            $userFolder = $this->rootFolder->getUserFolder($userId);
1023
+        } catch (NoUserException $e) {
1024
+            throw new InvalidShare();
1025
+        }
1026
+
1027
+        $nodes = $userFolder->getById($id);
1028
+
1029
+        if (empty($nodes)) {
1030
+            throw new InvalidShare();
1031
+        }
1032
+
1033
+        return $nodes[0];
1034
+    }
1035
+
1036
+    /**
1037
+     * A user is deleted from the system
1038
+     * So clean up the relevant shares.
1039
+     *
1040
+     * @param string $uid
1041
+     * @param int $shareType
1042
+     */
1043
+    public function userDeleted($uid, $shareType) {
1044
+        $qb = $this->dbConnection->getQueryBuilder();
1045
+
1046
+        $qb->delete('share')
1047
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
1048
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
1049
+            ->execute();
1050
+    }
1051
+
1052
+    /**
1053
+     * This provider does not support group shares
1054
+     *
1055
+     * @param string $gid
1056
+     */
1057
+    public function groupDeleted($gid) {
1058
+    }
1059
+
1060
+    /**
1061
+     * This provider does not support group shares
1062
+     *
1063
+     * @param string $uid
1064
+     * @param string $gid
1065
+     */
1066
+    public function userDeletedFromGroup($uid, $gid) {
1067
+    }
1068
+
1069
+    /**
1070
+     * get database row of a give share
1071
+     *
1072
+     * @param $id
1073
+     * @return array
1074
+     * @throws ShareNotFound
1075
+     */
1076
+    protected function getRawShare($id) {
1077
+
1078
+        // Now fetch the inserted share and create a complete share object
1079
+        $qb = $this->dbConnection->getQueryBuilder();
1080
+        $qb->select('*')
1081
+            ->from('share')
1082
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1083
+
1084
+        $cursor = $qb->execute();
1085
+        $data = $cursor->fetch();
1086
+        $cursor->closeCursor();
1087
+
1088
+        if ($data === false) {
1089
+            throw new ShareNotFound;
1090
+        }
1091
+
1092
+        return $data;
1093
+    }
1094
+
1095
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
1096
+        $qb = $this->dbConnection->getQueryBuilder();
1097
+        $qb->select('*')
1098
+            ->from('share', 's')
1099
+            ->andWhere($qb->expr()->orX(
1100
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1101
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1102
+            ))
1103
+            ->andWhere(
1104
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
1105
+            );
1106
+
1107
+        /**
1108
+         * Reshares for this user are shares where they are the owner.
1109
+         */
1110
+        if ($reshares === false) {
1111
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1112
+        } else {
1113
+            $qb->andWhere(
1114
+                $qb->expr()->orX(
1115
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1116
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1117
+                )
1118
+            );
1119
+        }
1120
+
1121
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1122
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1123
+
1124
+        $qb->orderBy('id');
1125
+
1126
+        $cursor = $qb->execute();
1127
+        $shares = [];
1128
+        while ($data = $cursor->fetch()) {
1129
+            $shares[$data['fileid']][] = $this->createShareObject($data);
1130
+        }
1131
+        $cursor->closeCursor();
1132
+
1133
+        return $shares;
1134
+    }
1135
+
1136
+    /**
1137
+     * @inheritdoc
1138
+     */
1139
+    public function getAccessList($nodes, $currentAccess) {
1140
+        $ids = [];
1141
+        foreach ($nodes as $node) {
1142
+            $ids[] = $node->getId();
1143
+        }
1144
+
1145
+        $qb = $this->dbConnection->getQueryBuilder();
1146
+        $qb->select('share_with')
1147
+            ->from('share')
1148
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
1149
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1150
+            ->andWhere($qb->expr()->orX(
1151
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1152
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1153
+            ))
1154
+            ->setMaxResults(1);
1155
+        $cursor = $qb->execute();
1156
+
1157
+        $mail = $cursor->fetch() !== false;
1158
+        $cursor->closeCursor();
1159
+
1160
+        return ['public' => $mail];
1161
+    }
1162 1162
 
1163 1163
 }
Please login to merge, or discard this patch.
Spacing   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -211,10 +211,10 @@  discard block
 block discarded – undo
211 211
 		}
212 212
 
213 213
 		$passwordPolicy = $this->getPasswordPolicy();
214
-		$passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS;
214
+		$passwordCharset = ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_DIGITS;
215 215
 		$passwordLength = 8;
216 216
 		if (!empty($passwordPolicy)) {
217
-			$passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength;
217
+			$passwordLength = (int) $passwordPolicy['minLength'] > 0 ? (int) $passwordPolicy['minLength'] : $passwordLength;
218 218
 			$passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : '';
219 219
 		}
220 220
 
@@ -406,7 +406,7 @@  discard block
 block discarded – undo
406 406
 		$text = $this->l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
407 407
 
408 408
 		$emailTemplate->addBodyText(
409
-			htmlspecialchars($text . ' ' . $this->l->t('Click the button below to open it.')),
409
+			htmlspecialchars($text.' '.$this->l->t('Click the button below to open it.')),
410 410
 			$text
411 411
 		);
412 412
 		$emailTemplate->addBodyButton(
@@ -430,9 +430,9 @@  discard block
 block discarded – undo
430 430
 		// The "Reply-To" is set to the sharer if an mail address is configured
431 431
 		// also the default footer contains a "Do not reply" which needs to be adjusted.
432 432
 		$initiatorEmail = $initiatorUser->getEMailAddress();
433
-		if($initiatorEmail !== null) {
433
+		if ($initiatorEmail !== null) {
434 434
 			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
435
-			$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
435
+			$emailTemplate->addFooter($instanceName.($this->defaults->getSlogan() !== '' ? ' - '.$this->defaults->getSlogan() : ''));
436 436
 		} else {
437 437
 			$emailTemplate->addFooter();
438 438
 		}
@@ -494,7 +494,7 @@  discard block
 block discarded – undo
494 494
 		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
495 495
 		if ($initiatorEmailAddress !== null) {
496 496
 			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
497
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
497
+			$emailTemplate->addFooter($instanceName.' - '.$this->defaults->getSlogan());
498 498
 		} else {
499 499
 			$emailTemplate->addFooter();
500 500
 		}
@@ -552,7 +552,7 @@  discard block
 block discarded – undo
552 552
 		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
553 553
 		if ($initiatorEmailAddress !== null) {
554 554
 			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
555
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
555
+			$emailTemplate->addFooter($instanceName.' - '.$this->defaults->getSlogan());
556 556
 		} else {
557 557
 			$emailTemplate->addFooter();
558 558
 		}
@@ -645,7 +645,7 @@  discard block
 block discarded – undo
645 645
 			->orderBy('id');
646 646
 
647 647
 		$cursor = $qb->execute();
648
-		while($data = $cursor->fetch()) {
648
+		while ($data = $cursor->fetch()) {
649 649
 			$children[] = $this->createShareObject($data);
650 650
 		}
651 651
 		$cursor->closeCursor();
@@ -692,7 +692,7 @@  discard block
 block discarded – undo
692 692
 		$qb->execute();
693 693
 		$id = $qb->getLastInsertId();
694 694
 
695
-		return (int)$id;
695
+		return (int) $id;
696 696
 	}
697 697
 
698 698
 	/**
@@ -709,7 +709,7 @@  discard block
 block discarded – undo
709 709
 		// a real password was given
710 710
 		$validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
711 711
 
712
-		if($validPassword && ($originalShare->getPassword() !== $share->getPassword() ||
712
+		if ($validPassword && ($originalShare->getPassword() !== $share->getPassword() ||
713 713
 								($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()))) {
714 714
 			$this->sendPassword($share, $plainTextPassword);
715 715
 		}
@@ -813,7 +813,7 @@  discard block
 block discarded – undo
813 813
 
814 814
 		$cursor = $qb->execute();
815 815
 		$shares = [];
816
-		while($data = $cursor->fetch()) {
816
+		while ($data = $cursor->fetch()) {
817 817
 			$shares[] = $this->createShareObject($data);
818 818
 		}
819 819
 		$cursor->closeCursor();
@@ -865,7 +865,7 @@  discard block
 block discarded – undo
865 865
 			->execute();
866 866
 
867 867
 		$shares = [];
868
-		while($data = $cursor->fetch()) {
868
+		while ($data = $cursor->fetch()) {
869 869
 			$shares[] = $this->createShareObject($data);
870 870
 		}
871 871
 		$cursor->closeCursor();
@@ -904,7 +904,7 @@  discard block
 block discarded – undo
904 904
 
905 905
 		$cursor = $qb->execute();
906 906
 
907
-		while($data = $cursor->fetch()) {
907
+		while ($data = $cursor->fetch()) {
908 908
 			$shares[] = $this->createShareObject($data);
909 909
 		}
910 910
 		$cursor->closeCursor();
@@ -967,16 +967,16 @@  discard block
 block discarded – undo
967 967
 	protected function createShareObject($data) {
968 968
 
969 969
 		$share = new Share($this->rootFolder, $this->userManager);
970
-		$share->setId((int)$data['id'])
971
-			->setShareType((int)$data['share_type'])
972
-			->setPermissions((int)$data['permissions'])
970
+		$share->setId((int) $data['id'])
971
+			->setShareType((int) $data['share_type'])
972
+			->setPermissions((int) $data['permissions'])
973 973
 			->setTarget($data['file_target'])
974
-			->setMailSend((bool)$data['mail_send'])
974
+			->setMailSend((bool) $data['mail_send'])
975 975
 			->setNote($data['note'])
976 976
 			->setToken($data['token']);
977 977
 
978 978
 		$shareTime = new \DateTime();
979
-		$shareTime->setTimestamp((int)$data['stime']);
979
+		$shareTime->setTimestamp((int) $data['stime']);
980 980
 		$share->setShareTime($shareTime);
981 981
 		$share->setSharedWith($data['share_with']);
982 982
 		$share->setPassword($data['password']);
@@ -988,7 +988,7 @@  discard block
 block discarded – undo
988 988
 		} else {
989 989
 			//OLD SHARE
990 990
 			$share->setSharedBy($data['uid_owner']);
991
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
991
+			$path = $this->getNode($share->getSharedBy(), (int) $data['file_source']);
992 992
 
993 993
 			$owner = $path->getOwner();
994 994
 			$share->setShareOwner($owner->getUID());
@@ -1001,7 +1001,7 @@  discard block
 block discarded – undo
1001 1001
 			}
1002 1002
 		}
1003 1003
 
1004
-		$share->setNodeId((int)$data['file_source']);
1004
+		$share->setNodeId((int) $data['file_source']);
1005 1005
 		$share->setNodeType($data['item_type']);
1006 1006
 
1007 1007
 		$share->setProviderId($this->identifier());
@@ -1118,7 +1118,7 @@  discard block
 block discarded – undo
1118 1118
 			);
1119 1119
 		}
1120 1120
 
1121
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1121
+		$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1122 1122
 		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1123 1123
 
1124 1124
 		$qb->orderBy('id');
Please login to merge, or discard this patch.
apps/files_sharing/lib/Controller/ShareAPIController.php 3 patches
Indentation   +1004 added lines, -1004 removed lines patch added patch discarded remove patch
@@ -66,1017 +66,1017 @@
 block discarded – undo
66 66
  */
67 67
 class ShareAPIController extends OCSController {
68 68
 
69
-	/** @var IManager */
70
-	private $shareManager;
71
-	/** @var IGroupManager */
72
-	private $groupManager;
73
-	/** @var IUserManager */
74
-	private $userManager;
75
-	/** @var IRootFolder */
76
-	private $rootFolder;
77
-	/** @var IURLGenerator */
78
-	private $urlGenerator;
79
-	/** @var string */
80
-	private $currentUser;
81
-	/** @var IL10N */
82
-	private $l;
83
-	/** @var \OCP\Files\Node */
84
-	private $lockedNode;
85
-	/** @var IConfig */
86
-	private $config;
87
-	/** @var IAppManager */
88
-	private $appManager;
89
-	/** @var IServerContainer */
90
-	private $serverContainer;
91
-
92
-	/**
93
-	 * Share20OCS constructor.
94
-	 *
95
-	 * @param string $appName
96
-	 * @param IRequest $request
97
-	 * @param IManager $shareManager
98
-	 * @param IGroupManager $groupManager
99
-	 * @param IUserManager $userManager
100
-	 * @param IRootFolder $rootFolder
101
-	 * @param IURLGenerator $urlGenerator
102
-	 * @param string $userId
103
-	 * @param IL10N $l10n
104
-	 * @param IConfig $config
105
-	 * @param IAppManager $appManager
106
-	 * @param IServerContainer $serverContainer
107
-	 */
108
-	public function __construct(
109
-		string $appName,
110
-		IRequest $request,
111
-		IManager $shareManager,
112
-		IGroupManager $groupManager,
113
-		IUserManager $userManager,
114
-		IRootFolder $rootFolder,
115
-		IURLGenerator $urlGenerator,
116
-		string $userId = null,
117
-		IL10N $l10n,
118
-		IConfig $config,
119
-		IAppManager $appManager,
120
-		IServerContainer $serverContainer
121
-	) {
122
-		parent::__construct($appName, $request);
123
-
124
-		$this->shareManager = $shareManager;
125
-		$this->userManager = $userManager;
126
-		$this->groupManager = $groupManager;
127
-		$this->request = $request;
128
-		$this->rootFolder = $rootFolder;
129
-		$this->urlGenerator = $urlGenerator;
130
-		$this->currentUser = $userId;
131
-		$this->l = $l10n;
132
-		$this->config = $config;
133
-		$this->appManager = $appManager;
134
-		$this->serverContainer = $serverContainer;
135
-	}
136
-
137
-	/**
138
-	 * Convert an IShare to an array for OCS output
139
-	 *
140
-	 * @param \OCP\Share\IShare $share
141
-	 * @param Node|null $recipientNode
142
-	 * @return array
143
-	 * @throws NotFoundException In case the node can't be resolved.
144
-	 *
145
-	 * @suppress PhanUndeclaredClassMethod
146
-	 */
147
-	protected function formatShare(\OCP\Share\IShare $share, Node $recipientNode = null): array {
148
-		$sharedBy = $this->userManager->get($share->getSharedBy());
149
-		$shareOwner = $this->userManager->get($share->getShareOwner());
150
-
151
-		$result = [
152
-			'id' => $share->getId(),
153
-			'share_type' => $share->getShareType(),
154
-			'uid_owner' => $share->getSharedBy(),
155
-			'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(),
156
-			'permissions' => $share->getPermissions(),
157
-			'stime' => $share->getShareTime()->getTimestamp(),
158
-			'parent' => null,
159
-			'expiration' => null,
160
-			'token' => null,
161
-			'uid_file_owner' => $share->getShareOwner(),
162
-			'note' => $share->getNote(),
163
-			'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(),
164
-		];
165
-
166
-		$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
167
-		if ($recipientNode) {
168
-			$node = $recipientNode;
169
-		} else {
170
-			$nodes = $userFolder->getById($share->getNodeId());
171
-			if (empty($nodes)) {
172
-				// fallback to guessing the path
173
-				$node = $userFolder->get($share->getTarget());
174
-				if ($node === null || $share->getTarget() === '') {
175
-					throw new NotFoundException();
176
-				}
177
-			} else {
178
-				$node = $nodes[0];
179
-			}
180
-		}
181
-
182
-		$result['path'] = $userFolder->getRelativePath($node->getPath());
183
-		if ($node instanceOf \OCP\Files\Folder) {
184
-			$result['item_type'] = 'folder';
185
-		} else {
186
-			$result['item_type'] = 'file';
187
-		}
188
-		$result['mimetype'] = $node->getMimetype();
189
-		$result['storage_id'] = $node->getStorage()->getId();
190
-		$result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
191
-		$result['item_source'] = $node->getId();
192
-		$result['file_source'] = $node->getId();
193
-		$result['file_parent'] = $node->getParent()->getId();
194
-		$result['file_target'] = $share->getTarget();
195
-
196
-		$expiration = $share->getExpirationDate();
197
-		if ($expiration !== null) {
198
-			$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
199
-		}
200
-
201
-		if ($share->getShareType() === Share::SHARE_TYPE_USER) {
202
-			$sharedWith = $this->userManager->get($share->getSharedWith());
203
-			$result['share_with'] = $share->getSharedWith();
204
-			$result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith();
205
-		} else if ($share->getShareType() === Share::SHARE_TYPE_GROUP) {
206
-			$group = $this->groupManager->get($share->getSharedWith());
207
-			$result['share_with'] = $share->getSharedWith();
208
-			$result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
209
-		} else if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
210
-
211
-			$result['share_with'] = $share->getPassword();
212
-			$result['share_with_displayname'] = $share->getPassword();
213
-
214
-			$result['token'] = $share->getToken();
215
-			$result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
216
-
217
-		} else if ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() === Share::SHARE_TYPE_REMOTE_GROUP) {
218
-			$result['share_with'] = $share->getSharedWith();
219
-			$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
220
-			$result['token'] = $share->getToken();
221
-		} else if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
222
-			$result['share_with'] = $share->getSharedWith();
223
-			$result['password'] = $share->getPassword();
224
-			$result['send_password_by_talk'] = $share->getSendPasswordByTalk();
225
-			$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
226
-			$result['token'] = $share->getToken();
227
-		} else if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
228
-			// getSharedWith() returns either "name (type, owner)" or
229
-			// "name (type, owner) [id]", depending on the Circles app version.
230
-			$hasCircleId = (substr($share->getSharedWith(), -1) === ']');
231
-
232
-			$result['share_with_displayname'] = $share->getSharedWithDisplayName();
233
-			if (empty($result['share_with_displayname'])) {
234
-				$displayNameLength = ($hasCircleId? strrpos($share->getSharedWith(), ' '): strlen($share->getSharedWith()));
235
-				$result['share_with_displayname'] = substr($share->getSharedWith(), 0, $displayNameLength);
236
-			}
237
-
238
-			$result['share_with_avatar'] = $share->getSharedWithAvatar();
239
-
240
-			$shareWithStart = ($hasCircleId? strrpos($share->getSharedWith(), '[') + 1: 0);
241
-			$shareWithLength = ($hasCircleId? -1: strpos($share->getSharedWith(), ' '));
242
-			$result['share_with'] = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
243
-		} else if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
244
-			$result['share_with'] = $share->getSharedWith();
245
-			$result['share_with_displayname'] = '';
246
-
247
-			try {
248
-				$result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
249
-			} catch (QueryException $e) {
250
-			}
251
-		}
252
-
253
-
254
-		$result['mail_send'] = $share->getMailSend() ? 1 : 0;
255
-
256
-		return $result;
257
-	}
258
-
259
-	/**
260
-	 * Check if one of the users address books knows the exact property, if
261
-	 * yes we return the full name.
262
-	 *
263
-	 * @param string $query
264
-	 * @param string $property
265
-	 * @return string
266
-	 */
267
-	private function getDisplayNameFromAddressBook(string $query, string $property): string {
268
-		// FIXME: If we inject the contacts manager it gets initialized bofore any address books are registered
269
-		$result = \OC::$server->getContactsManager()->search($query, [$property]);
270
-		foreach ($result as $r) {
271
-			foreach($r[$property] as $value) {
272
-				if ($value === $query) {
273
-					return $r['FN'];
274
-				}
275
-			}
276
-		}
277
-
278
-		return $query;
279
-	}
280
-
281
-	/**
282
-	 * Get a specific share by id
283
-	 *
284
-	 * @NoAdminRequired
285
-	 *
286
-	 * @param string $id
287
-	 * @return DataResponse
288
-	 * @throws OCSNotFoundException
289
-	 */
290
-	public function getShare(string $id): DataResponse {
291
-		try {
292
-			$share = $this->getShareById($id);
293
-		} catch (ShareNotFound $e) {
294
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
295
-		}
296
-
297
-		if ($this->canAccessShare($share)) {
298
-			try {
299
-				$share = $this->formatShare($share);
300
-				return new DataResponse([$share]);
301
-			} catch (NotFoundException $e) {
302
-				//Fall trough
303
-			}
304
-		}
305
-
306
-		throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
307
-	}
308
-
309
-	/**
310
-	 * Delete a share
311
-	 *
312
-	 * @NoAdminRequired
313
-	 *
314
-	 * @param string $id
315
-	 * @return DataResponse
316
-	 * @throws OCSNotFoundException
317
-	 */
318
-	public function deleteShare(string $id): DataResponse {
319
-		try {
320
-			$share = $this->getShareById($id);
321
-		} catch (ShareNotFound $e) {
322
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
323
-		}
324
-
325
-		try {
326
-			$this->lock($share->getNode());
327
-		} catch (LockedException $e) {
328
-			throw new OCSNotFoundException($this->l->t('could not delete share'));
329
-		}
330
-
331
-		if (!$this->canAccessShare($share)) {
332
-			throw new OCSNotFoundException($this->l->t('Could not delete share'));
333
-		}
334
-
335
-		if (($share->getShareType() === Share::SHARE_TYPE_GROUP ||
336
-				$share->getShareType() === Share::SHARE_TYPE_ROOM) &&
337
-			$share->getShareOwner() !== $this->currentUser &&
338
-			$share->getSharedBy() !== $this->currentUser) {
339
-			$this->shareManager->deleteFromSelf($share, $this->currentUser);
340
-		} else {
341
-			$this->shareManager->deleteShare($share);
342
-		}
343
-
344
-		return new DataResponse();
345
-	}
346
-
347
-	/**
348
-	 * @NoAdminRequired
349
-	 *
350
-	 * @param string $path
351
-	 * @param int $permissions
352
-	 * @param int $shareType
353
-	 * @param string $shareWith
354
-	 * @param string $publicUpload
355
-	 * @param string $password
356
-	 * @param bool $sendPasswordByTalk
357
-	 * @param string $expireDate
358
-	 *
359
-	 * @return DataResponse
360
-	 * @throws OCSNotFoundException
361
-	 * @throws OCSForbiddenException
362
-	 * @throws OCSBadRequestException
363
-	 * @throws OCSException
364
-	 *
365
-	 * @suppress PhanUndeclaredClassMethod
366
-	 */
367
-	public function createShare(
368
-		string $path = null,
369
-		int $permissions = null,
370
-		int $shareType = -1,
371
-		string $shareWith = null,
372
-		string $publicUpload = 'false',
373
-		string $password = '',
374
-		string $sendPasswordByTalk = null,
375
-		string $expireDate = ''
376
-	): DataResponse {
377
-		$share = $this->shareManager->newShare();
378
-
379
-		if ($permissions === null) {
380
-			$permissions = $this->config->getAppValue('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL);
381
-		}
382
-
383
-		// Verify path
384
-		if ($path === null) {
385
-			throw new OCSNotFoundException($this->l->t('Please specify a file or folder path'));
386
-		}
387
-
388
-		$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
389
-		try {
390
-			$path = $userFolder->get($path);
391
-		} catch (NotFoundException $e) {
392
-			throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
393
-		}
394
-
395
-		$share->setNode($path);
396
-
397
-		try {
398
-			$this->lock($share->getNode());
399
-		} catch (LockedException $e) {
400
-			throw new OCSNotFoundException($this->l->t('Could not create share'));
401
-		}
402
-
403
-		if ($permissions < 0 || $permissions > Constants::PERMISSION_ALL) {
404
-			throw new OCSNotFoundException($this->l->t('invalid permissions'));
405
-		}
406
-
407
-		// Shares always require read permissions
408
-		$permissions |= Constants::PERMISSION_READ;
409
-
410
-		if ($path instanceof \OCP\Files\File) {
411
-			// Single file shares should never have delete or create permissions
412
-			$permissions &= ~Constants::PERMISSION_DELETE;
413
-			$permissions &= ~Constants::PERMISSION_CREATE;
414
-		}
415
-
416
-		/*
69
+    /** @var IManager */
70
+    private $shareManager;
71
+    /** @var IGroupManager */
72
+    private $groupManager;
73
+    /** @var IUserManager */
74
+    private $userManager;
75
+    /** @var IRootFolder */
76
+    private $rootFolder;
77
+    /** @var IURLGenerator */
78
+    private $urlGenerator;
79
+    /** @var string */
80
+    private $currentUser;
81
+    /** @var IL10N */
82
+    private $l;
83
+    /** @var \OCP\Files\Node */
84
+    private $lockedNode;
85
+    /** @var IConfig */
86
+    private $config;
87
+    /** @var IAppManager */
88
+    private $appManager;
89
+    /** @var IServerContainer */
90
+    private $serverContainer;
91
+
92
+    /**
93
+     * Share20OCS constructor.
94
+     *
95
+     * @param string $appName
96
+     * @param IRequest $request
97
+     * @param IManager $shareManager
98
+     * @param IGroupManager $groupManager
99
+     * @param IUserManager $userManager
100
+     * @param IRootFolder $rootFolder
101
+     * @param IURLGenerator $urlGenerator
102
+     * @param string $userId
103
+     * @param IL10N $l10n
104
+     * @param IConfig $config
105
+     * @param IAppManager $appManager
106
+     * @param IServerContainer $serverContainer
107
+     */
108
+    public function __construct(
109
+        string $appName,
110
+        IRequest $request,
111
+        IManager $shareManager,
112
+        IGroupManager $groupManager,
113
+        IUserManager $userManager,
114
+        IRootFolder $rootFolder,
115
+        IURLGenerator $urlGenerator,
116
+        string $userId = null,
117
+        IL10N $l10n,
118
+        IConfig $config,
119
+        IAppManager $appManager,
120
+        IServerContainer $serverContainer
121
+    ) {
122
+        parent::__construct($appName, $request);
123
+
124
+        $this->shareManager = $shareManager;
125
+        $this->userManager = $userManager;
126
+        $this->groupManager = $groupManager;
127
+        $this->request = $request;
128
+        $this->rootFolder = $rootFolder;
129
+        $this->urlGenerator = $urlGenerator;
130
+        $this->currentUser = $userId;
131
+        $this->l = $l10n;
132
+        $this->config = $config;
133
+        $this->appManager = $appManager;
134
+        $this->serverContainer = $serverContainer;
135
+    }
136
+
137
+    /**
138
+     * Convert an IShare to an array for OCS output
139
+     *
140
+     * @param \OCP\Share\IShare $share
141
+     * @param Node|null $recipientNode
142
+     * @return array
143
+     * @throws NotFoundException In case the node can't be resolved.
144
+     *
145
+     * @suppress PhanUndeclaredClassMethod
146
+     */
147
+    protected function formatShare(\OCP\Share\IShare $share, Node $recipientNode = null): array {
148
+        $sharedBy = $this->userManager->get($share->getSharedBy());
149
+        $shareOwner = $this->userManager->get($share->getShareOwner());
150
+
151
+        $result = [
152
+            'id' => $share->getId(),
153
+            'share_type' => $share->getShareType(),
154
+            'uid_owner' => $share->getSharedBy(),
155
+            'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(),
156
+            'permissions' => $share->getPermissions(),
157
+            'stime' => $share->getShareTime()->getTimestamp(),
158
+            'parent' => null,
159
+            'expiration' => null,
160
+            'token' => null,
161
+            'uid_file_owner' => $share->getShareOwner(),
162
+            'note' => $share->getNote(),
163
+            'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(),
164
+        ];
165
+
166
+        $userFolder = $this->rootFolder->getUserFolder($this->currentUser);
167
+        if ($recipientNode) {
168
+            $node = $recipientNode;
169
+        } else {
170
+            $nodes = $userFolder->getById($share->getNodeId());
171
+            if (empty($nodes)) {
172
+                // fallback to guessing the path
173
+                $node = $userFolder->get($share->getTarget());
174
+                if ($node === null || $share->getTarget() === '') {
175
+                    throw new NotFoundException();
176
+                }
177
+            } else {
178
+                $node = $nodes[0];
179
+            }
180
+        }
181
+
182
+        $result['path'] = $userFolder->getRelativePath($node->getPath());
183
+        if ($node instanceOf \OCP\Files\Folder) {
184
+            $result['item_type'] = 'folder';
185
+        } else {
186
+            $result['item_type'] = 'file';
187
+        }
188
+        $result['mimetype'] = $node->getMimetype();
189
+        $result['storage_id'] = $node->getStorage()->getId();
190
+        $result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
191
+        $result['item_source'] = $node->getId();
192
+        $result['file_source'] = $node->getId();
193
+        $result['file_parent'] = $node->getParent()->getId();
194
+        $result['file_target'] = $share->getTarget();
195
+
196
+        $expiration = $share->getExpirationDate();
197
+        if ($expiration !== null) {
198
+            $result['expiration'] = $expiration->format('Y-m-d 00:00:00');
199
+        }
200
+
201
+        if ($share->getShareType() === Share::SHARE_TYPE_USER) {
202
+            $sharedWith = $this->userManager->get($share->getSharedWith());
203
+            $result['share_with'] = $share->getSharedWith();
204
+            $result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith();
205
+        } else if ($share->getShareType() === Share::SHARE_TYPE_GROUP) {
206
+            $group = $this->groupManager->get($share->getSharedWith());
207
+            $result['share_with'] = $share->getSharedWith();
208
+            $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
209
+        } else if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
210
+
211
+            $result['share_with'] = $share->getPassword();
212
+            $result['share_with_displayname'] = $share->getPassword();
213
+
214
+            $result['token'] = $share->getToken();
215
+            $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
216
+
217
+        } else if ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() === Share::SHARE_TYPE_REMOTE_GROUP) {
218
+            $result['share_with'] = $share->getSharedWith();
219
+            $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
220
+            $result['token'] = $share->getToken();
221
+        } else if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
222
+            $result['share_with'] = $share->getSharedWith();
223
+            $result['password'] = $share->getPassword();
224
+            $result['send_password_by_talk'] = $share->getSendPasswordByTalk();
225
+            $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
226
+            $result['token'] = $share->getToken();
227
+        } else if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
228
+            // getSharedWith() returns either "name (type, owner)" or
229
+            // "name (type, owner) [id]", depending on the Circles app version.
230
+            $hasCircleId = (substr($share->getSharedWith(), -1) === ']');
231
+
232
+            $result['share_with_displayname'] = $share->getSharedWithDisplayName();
233
+            if (empty($result['share_with_displayname'])) {
234
+                $displayNameLength = ($hasCircleId? strrpos($share->getSharedWith(), ' '): strlen($share->getSharedWith()));
235
+                $result['share_with_displayname'] = substr($share->getSharedWith(), 0, $displayNameLength);
236
+            }
237
+
238
+            $result['share_with_avatar'] = $share->getSharedWithAvatar();
239
+
240
+            $shareWithStart = ($hasCircleId? strrpos($share->getSharedWith(), '[') + 1: 0);
241
+            $shareWithLength = ($hasCircleId? -1: strpos($share->getSharedWith(), ' '));
242
+            $result['share_with'] = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
243
+        } else if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
244
+            $result['share_with'] = $share->getSharedWith();
245
+            $result['share_with_displayname'] = '';
246
+
247
+            try {
248
+                $result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
249
+            } catch (QueryException $e) {
250
+            }
251
+        }
252
+
253
+
254
+        $result['mail_send'] = $share->getMailSend() ? 1 : 0;
255
+
256
+        return $result;
257
+    }
258
+
259
+    /**
260
+     * Check if one of the users address books knows the exact property, if
261
+     * yes we return the full name.
262
+     *
263
+     * @param string $query
264
+     * @param string $property
265
+     * @return string
266
+     */
267
+    private function getDisplayNameFromAddressBook(string $query, string $property): string {
268
+        // FIXME: If we inject the contacts manager it gets initialized bofore any address books are registered
269
+        $result = \OC::$server->getContactsManager()->search($query, [$property]);
270
+        foreach ($result as $r) {
271
+            foreach($r[$property] as $value) {
272
+                if ($value === $query) {
273
+                    return $r['FN'];
274
+                }
275
+            }
276
+        }
277
+
278
+        return $query;
279
+    }
280
+
281
+    /**
282
+     * Get a specific share by id
283
+     *
284
+     * @NoAdminRequired
285
+     *
286
+     * @param string $id
287
+     * @return DataResponse
288
+     * @throws OCSNotFoundException
289
+     */
290
+    public function getShare(string $id): DataResponse {
291
+        try {
292
+            $share = $this->getShareById($id);
293
+        } catch (ShareNotFound $e) {
294
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
295
+        }
296
+
297
+        if ($this->canAccessShare($share)) {
298
+            try {
299
+                $share = $this->formatShare($share);
300
+                return new DataResponse([$share]);
301
+            } catch (NotFoundException $e) {
302
+                //Fall trough
303
+            }
304
+        }
305
+
306
+        throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
307
+    }
308
+
309
+    /**
310
+     * Delete a share
311
+     *
312
+     * @NoAdminRequired
313
+     *
314
+     * @param string $id
315
+     * @return DataResponse
316
+     * @throws OCSNotFoundException
317
+     */
318
+    public function deleteShare(string $id): DataResponse {
319
+        try {
320
+            $share = $this->getShareById($id);
321
+        } catch (ShareNotFound $e) {
322
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
323
+        }
324
+
325
+        try {
326
+            $this->lock($share->getNode());
327
+        } catch (LockedException $e) {
328
+            throw new OCSNotFoundException($this->l->t('could not delete share'));
329
+        }
330
+
331
+        if (!$this->canAccessShare($share)) {
332
+            throw new OCSNotFoundException($this->l->t('Could not delete share'));
333
+        }
334
+
335
+        if (($share->getShareType() === Share::SHARE_TYPE_GROUP ||
336
+                $share->getShareType() === Share::SHARE_TYPE_ROOM) &&
337
+            $share->getShareOwner() !== $this->currentUser &&
338
+            $share->getSharedBy() !== $this->currentUser) {
339
+            $this->shareManager->deleteFromSelf($share, $this->currentUser);
340
+        } else {
341
+            $this->shareManager->deleteShare($share);
342
+        }
343
+
344
+        return new DataResponse();
345
+    }
346
+
347
+    /**
348
+     * @NoAdminRequired
349
+     *
350
+     * @param string $path
351
+     * @param int $permissions
352
+     * @param int $shareType
353
+     * @param string $shareWith
354
+     * @param string $publicUpload
355
+     * @param string $password
356
+     * @param bool $sendPasswordByTalk
357
+     * @param string $expireDate
358
+     *
359
+     * @return DataResponse
360
+     * @throws OCSNotFoundException
361
+     * @throws OCSForbiddenException
362
+     * @throws OCSBadRequestException
363
+     * @throws OCSException
364
+     *
365
+     * @suppress PhanUndeclaredClassMethod
366
+     */
367
+    public function createShare(
368
+        string $path = null,
369
+        int $permissions = null,
370
+        int $shareType = -1,
371
+        string $shareWith = null,
372
+        string $publicUpload = 'false',
373
+        string $password = '',
374
+        string $sendPasswordByTalk = null,
375
+        string $expireDate = ''
376
+    ): DataResponse {
377
+        $share = $this->shareManager->newShare();
378
+
379
+        if ($permissions === null) {
380
+            $permissions = $this->config->getAppValue('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL);
381
+        }
382
+
383
+        // Verify path
384
+        if ($path === null) {
385
+            throw new OCSNotFoundException($this->l->t('Please specify a file or folder path'));
386
+        }
387
+
388
+        $userFolder = $this->rootFolder->getUserFolder($this->currentUser);
389
+        try {
390
+            $path = $userFolder->get($path);
391
+        } catch (NotFoundException $e) {
392
+            throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
393
+        }
394
+
395
+        $share->setNode($path);
396
+
397
+        try {
398
+            $this->lock($share->getNode());
399
+        } catch (LockedException $e) {
400
+            throw new OCSNotFoundException($this->l->t('Could not create share'));
401
+        }
402
+
403
+        if ($permissions < 0 || $permissions > Constants::PERMISSION_ALL) {
404
+            throw new OCSNotFoundException($this->l->t('invalid permissions'));
405
+        }
406
+
407
+        // Shares always require read permissions
408
+        $permissions |= Constants::PERMISSION_READ;
409
+
410
+        if ($path instanceof \OCP\Files\File) {
411
+            // Single file shares should never have delete or create permissions
412
+            $permissions &= ~Constants::PERMISSION_DELETE;
413
+            $permissions &= ~Constants::PERMISSION_CREATE;
414
+        }
415
+
416
+        /*
417 417
 		 * Hack for https://github.com/owncloud/core/issues/22587
418 418
 		 * We check the permissions via webdav. But the permissions of the mount point
419 419
 		 * do not equal the share permissions. Here we fix that for federated mounts.
420 420
 		 */
421
-		if ($path->getStorage()->instanceOfStorage(Storage::class)) {
422
-			$permissions &= ~($permissions & ~$path->getPermissions());
423
-		}
424
-
425
-		if ($shareType === Share::SHARE_TYPE_USER) {
426
-			// Valid user is required to share
427
-			if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
428
-				throw new OCSNotFoundException($this->l->t('Please specify a valid user'));
429
-			}
430
-			$share->setSharedWith($shareWith);
431
-			$share->setPermissions($permissions);
432
-		} else if ($shareType === Share::SHARE_TYPE_GROUP) {
433
-			if (!$this->shareManager->allowGroupSharing()) {
434
-				throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator'));
435
-			}
436
-
437
-			// Valid group is required to share
438
-			if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
439
-				throw new OCSNotFoundException($this->l->t('Please specify a valid group'));
440
-			}
441
-			$share->setSharedWith($shareWith);
442
-			$share->setPermissions($permissions);
443
-		} else if ($shareType === Share::SHARE_TYPE_LINK) {
444
-			//Can we even share links?
445
-			if (!$this->shareManager->shareApiAllowLinks()) {
446
-				throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator'));
447
-			}
448
-
449
-			/*
421
+        if ($path->getStorage()->instanceOfStorage(Storage::class)) {
422
+            $permissions &= ~($permissions & ~$path->getPermissions());
423
+        }
424
+
425
+        if ($shareType === Share::SHARE_TYPE_USER) {
426
+            // Valid user is required to share
427
+            if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
428
+                throw new OCSNotFoundException($this->l->t('Please specify a valid user'));
429
+            }
430
+            $share->setSharedWith($shareWith);
431
+            $share->setPermissions($permissions);
432
+        } else if ($shareType === Share::SHARE_TYPE_GROUP) {
433
+            if (!$this->shareManager->allowGroupSharing()) {
434
+                throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator'));
435
+            }
436
+
437
+            // Valid group is required to share
438
+            if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
439
+                throw new OCSNotFoundException($this->l->t('Please specify a valid group'));
440
+            }
441
+            $share->setSharedWith($shareWith);
442
+            $share->setPermissions($permissions);
443
+        } else if ($shareType === Share::SHARE_TYPE_LINK) {
444
+            //Can we even share links?
445
+            if (!$this->shareManager->shareApiAllowLinks()) {
446
+                throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator'));
447
+            }
448
+
449
+            /*
450 450
 			 * For now we only allow 1 link share.
451 451
 			 * Return the existing link share if this is a duplicate
452 452
 			 */
453
-			$existingShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, false, 1, 0);
454
-			if (!empty($existingShares)) {
455
-				return new DataResponse($this->formatShare($existingShares[0]));
456
-			}
457
-
458
-			if ($publicUpload === 'true') {
459
-				// Check if public upload is allowed
460
-				if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
461
-					throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
462
-				}
463
-
464
-				// Public upload can only be set for folders
465
-				if ($path instanceof \OCP\Files\File) {
466
-					throw new OCSNotFoundException($this->l->t('Public upload is only possible for publicly shared folders'));
467
-				}
468
-
469
-				$share->setPermissions(
470
-					Constants::PERMISSION_READ |
471
-					Constants::PERMISSION_CREATE |
472
-					Constants::PERMISSION_UPDATE |
473
-					Constants::PERMISSION_DELETE
474
-				);
475
-			} else {
476
-				$share->setPermissions(Constants::PERMISSION_READ);
477
-			}
478
-
479
-			// Set password
480
-			if ($password !== '') {
481
-				$share->setPassword($password);
482
-			}
483
-
484
-			//Expire date
485
-			if ($expireDate !== '') {
486
-				try {
487
-					$expireDate = $this->parseDate($expireDate);
488
-					$share->setExpirationDate($expireDate);
489
-				} catch (\Exception $e) {
490
-					throw new OCSNotFoundException($this->l->t('Invalid date, date format must be YYYY-MM-DD'));
491
-				}
492
-			}
493
-
494
-		} else if ($shareType === Share::SHARE_TYPE_REMOTE) {
495
-			if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
496
-				throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
497
-			}
498
-
499
-			$share->setSharedWith($shareWith);
500
-			$share->setPermissions($permissions);
501
-		}  else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) {
502
-			if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
503
-				throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
504
-			}
505
-
506
-			$share->setSharedWith($shareWith);
507
-			$share->setPermissions($permissions);
508
-		} else if ($shareType === Share::SHARE_TYPE_EMAIL) {
509
-			if ($share->getNodeType() === 'file') {
510
-				$share->setPermissions(Constants::PERMISSION_READ);
511
-			} else {
512
-				$share->setPermissions($permissions);
513
-			}
514
-			$share->setSharedWith($shareWith);
515
-
516
-			if ($sendPasswordByTalk === 'true') {
517
-				if (!$this->appManager->isEnabledForUser('spreed')) {
518
-					throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()]));
519
-				}
520
-
521
-				$share->setSendPasswordByTalk(true);
522
-			}
523
-		} else if ($shareType === Share::SHARE_TYPE_CIRCLE) {
524
-			if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) {
525
-				throw new OCSNotFoundException($this->l->t('You cannot share to a Circle if the app is not enabled'));
526
-			}
527
-
528
-			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($shareWith);
529
-
530
-			// Valid circle is required to share
531
-			if ($circle === null) {
532
-				throw new OCSNotFoundException($this->l->t('Please specify a valid circle'));
533
-			}
534
-			$share->setSharedWith($shareWith);
535
-			$share->setPermissions($permissions);
536
-		} else if ($shareType === Share::SHARE_TYPE_ROOM) {
537
-			try {
538
-				$this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate);
539
-			} catch (QueryException $e) {
540
-				throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()]));
541
-			}
542
-		} else {
543
-			throw new OCSBadRequestException($this->l->t('Unknown share type'));
544
-		}
545
-
546
-		$share->setShareType($shareType);
547
-		$share->setSharedBy($this->currentUser);
548
-
549
-		try {
550
-			$share = $this->shareManager->createShare($share);
551
-		} catch (GenericShareException $e) {
552
-			$code = $e->getCode() === 0 ? 403 : $e->getCode();
553
-			throw new OCSException($e->getHint(), $code);
554
-		} catch (\Exception $e) {
555
-			throw new OCSForbiddenException($e->getMessage(), $e);
556
-		}
557
-
558
-		$output = $this->formatShare($share);
559
-
560
-		return new DataResponse($output);
561
-	}
562
-
563
-	/**
564
-	 * @param \OCP\Files\File|\OCP\Files\Folder $node
565
-	 * @param boolean $includeTags
566
-	 * @return DataResponse
567
-	 */
568
-	private function getSharedWithMe($node = null, bool $includeTags): DataResponse {
569
-
570
-		$userShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $node, -1, 0);
571
-		$groupShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $node, -1, 0);
572
-		$circleShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_CIRCLE, $node, -1, 0);
573
-		$roomShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $node, -1, 0);
574
-
575
-		$shares = array_merge($userShares, $groupShares, $circleShares, $roomShares);
576
-
577
-		$shares = array_filter($shares, function (IShare $share) {
578
-			return $share->getShareOwner() !== $this->currentUser;
579
-		});
580
-
581
-		$formatted = [];
582
-		foreach ($shares as $share) {
583
-			if ($this->canAccessShare($share)) {
584
-				try {
585
-					$formatted[] = $this->formatShare($share);
586
-				} catch (NotFoundException $e) {
587
-					// Ignore this share
588
-				}
589
-			}
590
-		}
591
-
592
-		if ($includeTags) {
593
-			$formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
594
-		}
595
-
596
-		return new DataResponse($formatted);
597
-	}
598
-
599
-	/**
600
-	 * @param \OCP\Files\Folder $folder
601
-	 * @return DataResponse
602
-	 * @throws OCSBadRequestException
603
-	 */
604
-	private function getSharesInDir(Node $folder): DataResponse {
605
-		if (!($folder instanceof \OCP\Files\Folder)) {
606
-			throw new OCSBadRequestException($this->l->t('Not a directory'));
607
-		}
608
-
609
-		$nodes = $folder->getDirectoryListing();
610
-		/** @var \OCP\Share\IShare[] $shares */
611
-		$shares = [];
612
-		foreach ($nodes as $node) {
613
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $node, false, -1, 0));
614
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $node, false, -1, 0));
615
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $node, false, -1, 0));
616
-			if($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
617
-				$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $node, false, -1, 0));
618
-			}
619
-			if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
620
-				$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, false, -1, 0));
621
-			}
622
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $node, false, -1, 0));
623
-		}
624
-
625
-		$formatted = [];
626
-		foreach ($shares as $share) {
627
-			try {
628
-				$formatted[] = $this->formatShare($share);
629
-			} catch (NotFoundException $e) {
630
-				//Ignore this share
631
-			}
632
-		}
633
-
634
-		return new DataResponse($formatted);
635
-	}
636
-
637
-	/**
638
-	 * The getShares function.
639
-	 *
640
-	 * @NoAdminRequired
641
-	 *
642
-	 * @param string $shared_with_me
643
-	 * @param string $reshares
644
-	 * @param string $subfiles
645
-	 * @param string $path
646
-	 *
647
-	 * - Get shares by the current user
648
-	 * - Get shares by the current user and reshares (?reshares=true)
649
-	 * - Get shares with the current user (?shared_with_me=true)
650
-	 * - Get shares for a specific path (?path=...)
651
-	 * - Get all shares in a folder (?subfiles=true&path=..)
652
-	 *
653
-	 * @return DataResponse
654
-	 * @throws OCSNotFoundException
655
-	 */
656
-	public function getShares(
657
-		string $shared_with_me = 'false',
658
-		string $reshares = 'false',
659
-		string $subfiles = 'false',
660
-		string $path = null,
661
-		string $include_tags = 'false'
662
-	): DataResponse {
663
-
664
-		if ($path !== null) {
665
-			$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
666
-			try {
667
-				$path = $userFolder->get($path);
668
-				$this->lock($path);
669
-			} catch (\OCP\Files\NotFoundException $e) {
670
-				throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
671
-			} catch (LockedException $e) {
672
-				throw new OCSNotFoundException($this->l->t('Could not lock path'));
673
-			}
674
-		}
675
-
676
-		$include_tags = $include_tags === 'true';
677
-
678
-		if ($shared_with_me === 'true') {
679
-			$result = $this->getSharedWithMe($path, $include_tags);
680
-			return $result;
681
-		}
682
-
683
-		if ($subfiles === 'true') {
684
-			$result = $this->getSharesInDir($path);
685
-			return $result;
686
-		}
687
-
688
-		if ($reshares === 'true') {
689
-			$reshares = true;
690
-		} else {
691
-			$reshares = false;
692
-		}
693
-
694
-		// Get all shares
695
-		$userShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
696
-		$groupShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
697
-		$linkShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
698
-		if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
699
-			$mailShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0);
700
-		} else {
701
-			$mailShares = [];
702
-		}
703
-		if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
704
-			$circleShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0);
705
-		} else {
706
-			$circleShares = [];
707
-		}
708
-		$roomShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $path, $reshares, -1, 0);
709
-
710
-		$shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares);
711
-
712
-		if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
713
-			$federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
714
-			$shares = array_merge($shares, $federatedShares);
715
-		}
716
-
717
-		if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
718
-			$federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE_GROUP, $path, $reshares, -1, 0);
719
-			$shares = array_merge($shares, $federatedShares);
720
-		}
721
-
722
-		$formatted = [];
723
-		foreach ($shares as $share) {
724
-			try {
725
-				$formatted[] = $this->formatShare($share, $path);
726
-			} catch (NotFoundException $e) {
727
-				//Ignore share
728
-			}
729
-		}
730
-
731
-		if ($include_tags) {
732
-			$formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
733
-		}
734
-
735
-		return new DataResponse($formatted);
736
-	}
737
-
738
-	/**
739
-	 * @NoAdminRequired
740
-	 *
741
-	 * @param string $id
742
-	 * @param int $permissions
743
-	 * @param string $password
744
-	 * @param string $sendPasswordByTalk
745
-	 * @param string $publicUpload
746
-	 * @param string $expireDate
747
-	 * @param string $note
748
-	 * @return DataResponse
749
-	 * @throws LockedException
750
-	 * @throws NotFoundException
751
-	 * @throws OCSBadRequestException
752
-	 * @throws OCSForbiddenException
753
-	 * @throws OCSNotFoundException
754
-	 */
755
-	public function updateShare(
756
-		string $id,
757
-		int $permissions = null,
758
-		string $password = null,
759
-		string $sendPasswordByTalk = null,
760
-		string $publicUpload = null,
761
-		string $expireDate = null,
762
-		string $note = null
763
-	): DataResponse {
764
-		try {
765
-			$share = $this->getShareById($id);
766
-		} catch (ShareNotFound $e) {
767
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
768
-		}
769
-
770
-		$this->lock($share->getNode());
771
-
772
-		if (!$this->canAccessShare($share, false)) {
773
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
774
-		}
775
-
776
-		if ($permissions === null && $password === null && $sendPasswordByTalk === null && $publicUpload === null && $expireDate === null && $note === null) {
777
-			throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
778
-		}
779
-
780
-		if($note !== null) {
781
-			$share->setNote($note);
782
-		}
783
-
784
-		/*
453
+            $existingShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, false, 1, 0);
454
+            if (!empty($existingShares)) {
455
+                return new DataResponse($this->formatShare($existingShares[0]));
456
+            }
457
+
458
+            if ($publicUpload === 'true') {
459
+                // Check if public upload is allowed
460
+                if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
461
+                    throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
462
+                }
463
+
464
+                // Public upload can only be set for folders
465
+                if ($path instanceof \OCP\Files\File) {
466
+                    throw new OCSNotFoundException($this->l->t('Public upload is only possible for publicly shared folders'));
467
+                }
468
+
469
+                $share->setPermissions(
470
+                    Constants::PERMISSION_READ |
471
+                    Constants::PERMISSION_CREATE |
472
+                    Constants::PERMISSION_UPDATE |
473
+                    Constants::PERMISSION_DELETE
474
+                );
475
+            } else {
476
+                $share->setPermissions(Constants::PERMISSION_READ);
477
+            }
478
+
479
+            // Set password
480
+            if ($password !== '') {
481
+                $share->setPassword($password);
482
+            }
483
+
484
+            //Expire date
485
+            if ($expireDate !== '') {
486
+                try {
487
+                    $expireDate = $this->parseDate($expireDate);
488
+                    $share->setExpirationDate($expireDate);
489
+                } catch (\Exception $e) {
490
+                    throw new OCSNotFoundException($this->l->t('Invalid date, date format must be YYYY-MM-DD'));
491
+                }
492
+            }
493
+
494
+        } else if ($shareType === Share::SHARE_TYPE_REMOTE) {
495
+            if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
496
+                throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
497
+            }
498
+
499
+            $share->setSharedWith($shareWith);
500
+            $share->setPermissions($permissions);
501
+        }  else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) {
502
+            if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
503
+                throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
504
+            }
505
+
506
+            $share->setSharedWith($shareWith);
507
+            $share->setPermissions($permissions);
508
+        } else if ($shareType === Share::SHARE_TYPE_EMAIL) {
509
+            if ($share->getNodeType() === 'file') {
510
+                $share->setPermissions(Constants::PERMISSION_READ);
511
+            } else {
512
+                $share->setPermissions($permissions);
513
+            }
514
+            $share->setSharedWith($shareWith);
515
+
516
+            if ($sendPasswordByTalk === 'true') {
517
+                if (!$this->appManager->isEnabledForUser('spreed')) {
518
+                    throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()]));
519
+                }
520
+
521
+                $share->setSendPasswordByTalk(true);
522
+            }
523
+        } else if ($shareType === Share::SHARE_TYPE_CIRCLE) {
524
+            if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) {
525
+                throw new OCSNotFoundException($this->l->t('You cannot share to a Circle if the app is not enabled'));
526
+            }
527
+
528
+            $circle = \OCA\Circles\Api\v1\Circles::detailsCircle($shareWith);
529
+
530
+            // Valid circle is required to share
531
+            if ($circle === null) {
532
+                throw new OCSNotFoundException($this->l->t('Please specify a valid circle'));
533
+            }
534
+            $share->setSharedWith($shareWith);
535
+            $share->setPermissions($permissions);
536
+        } else if ($shareType === Share::SHARE_TYPE_ROOM) {
537
+            try {
538
+                $this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate);
539
+            } catch (QueryException $e) {
540
+                throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()]));
541
+            }
542
+        } else {
543
+            throw new OCSBadRequestException($this->l->t('Unknown share type'));
544
+        }
545
+
546
+        $share->setShareType($shareType);
547
+        $share->setSharedBy($this->currentUser);
548
+
549
+        try {
550
+            $share = $this->shareManager->createShare($share);
551
+        } catch (GenericShareException $e) {
552
+            $code = $e->getCode() === 0 ? 403 : $e->getCode();
553
+            throw new OCSException($e->getHint(), $code);
554
+        } catch (\Exception $e) {
555
+            throw new OCSForbiddenException($e->getMessage(), $e);
556
+        }
557
+
558
+        $output = $this->formatShare($share);
559
+
560
+        return new DataResponse($output);
561
+    }
562
+
563
+    /**
564
+     * @param \OCP\Files\File|\OCP\Files\Folder $node
565
+     * @param boolean $includeTags
566
+     * @return DataResponse
567
+     */
568
+    private function getSharedWithMe($node = null, bool $includeTags): DataResponse {
569
+
570
+        $userShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $node, -1, 0);
571
+        $groupShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $node, -1, 0);
572
+        $circleShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_CIRCLE, $node, -1, 0);
573
+        $roomShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $node, -1, 0);
574
+
575
+        $shares = array_merge($userShares, $groupShares, $circleShares, $roomShares);
576
+
577
+        $shares = array_filter($shares, function (IShare $share) {
578
+            return $share->getShareOwner() !== $this->currentUser;
579
+        });
580
+
581
+        $formatted = [];
582
+        foreach ($shares as $share) {
583
+            if ($this->canAccessShare($share)) {
584
+                try {
585
+                    $formatted[] = $this->formatShare($share);
586
+                } catch (NotFoundException $e) {
587
+                    // Ignore this share
588
+                }
589
+            }
590
+        }
591
+
592
+        if ($includeTags) {
593
+            $formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
594
+        }
595
+
596
+        return new DataResponse($formatted);
597
+    }
598
+
599
+    /**
600
+     * @param \OCP\Files\Folder $folder
601
+     * @return DataResponse
602
+     * @throws OCSBadRequestException
603
+     */
604
+    private function getSharesInDir(Node $folder): DataResponse {
605
+        if (!($folder instanceof \OCP\Files\Folder)) {
606
+            throw new OCSBadRequestException($this->l->t('Not a directory'));
607
+        }
608
+
609
+        $nodes = $folder->getDirectoryListing();
610
+        /** @var \OCP\Share\IShare[] $shares */
611
+        $shares = [];
612
+        foreach ($nodes as $node) {
613
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $node, false, -1, 0));
614
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $node, false, -1, 0));
615
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $node, false, -1, 0));
616
+            if($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
617
+                $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $node, false, -1, 0));
618
+            }
619
+            if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
620
+                $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, false, -1, 0));
621
+            }
622
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $node, false, -1, 0));
623
+        }
624
+
625
+        $formatted = [];
626
+        foreach ($shares as $share) {
627
+            try {
628
+                $formatted[] = $this->formatShare($share);
629
+            } catch (NotFoundException $e) {
630
+                //Ignore this share
631
+            }
632
+        }
633
+
634
+        return new DataResponse($formatted);
635
+    }
636
+
637
+    /**
638
+     * The getShares function.
639
+     *
640
+     * @NoAdminRequired
641
+     *
642
+     * @param string $shared_with_me
643
+     * @param string $reshares
644
+     * @param string $subfiles
645
+     * @param string $path
646
+     *
647
+     * - Get shares by the current user
648
+     * - Get shares by the current user and reshares (?reshares=true)
649
+     * - Get shares with the current user (?shared_with_me=true)
650
+     * - Get shares for a specific path (?path=...)
651
+     * - Get all shares in a folder (?subfiles=true&path=..)
652
+     *
653
+     * @return DataResponse
654
+     * @throws OCSNotFoundException
655
+     */
656
+    public function getShares(
657
+        string $shared_with_me = 'false',
658
+        string $reshares = 'false',
659
+        string $subfiles = 'false',
660
+        string $path = null,
661
+        string $include_tags = 'false'
662
+    ): DataResponse {
663
+
664
+        if ($path !== null) {
665
+            $userFolder = $this->rootFolder->getUserFolder($this->currentUser);
666
+            try {
667
+                $path = $userFolder->get($path);
668
+                $this->lock($path);
669
+            } catch (\OCP\Files\NotFoundException $e) {
670
+                throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
671
+            } catch (LockedException $e) {
672
+                throw new OCSNotFoundException($this->l->t('Could not lock path'));
673
+            }
674
+        }
675
+
676
+        $include_tags = $include_tags === 'true';
677
+
678
+        if ($shared_with_me === 'true') {
679
+            $result = $this->getSharedWithMe($path, $include_tags);
680
+            return $result;
681
+        }
682
+
683
+        if ($subfiles === 'true') {
684
+            $result = $this->getSharesInDir($path);
685
+            return $result;
686
+        }
687
+
688
+        if ($reshares === 'true') {
689
+            $reshares = true;
690
+        } else {
691
+            $reshares = false;
692
+        }
693
+
694
+        // Get all shares
695
+        $userShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
696
+        $groupShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
697
+        $linkShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
698
+        if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
699
+            $mailShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0);
700
+        } else {
701
+            $mailShares = [];
702
+        }
703
+        if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
704
+            $circleShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0);
705
+        } else {
706
+            $circleShares = [];
707
+        }
708
+        $roomShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $path, $reshares, -1, 0);
709
+
710
+        $shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares);
711
+
712
+        if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
713
+            $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
714
+            $shares = array_merge($shares, $federatedShares);
715
+        }
716
+
717
+        if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
718
+            $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE_GROUP, $path, $reshares, -1, 0);
719
+            $shares = array_merge($shares, $federatedShares);
720
+        }
721
+
722
+        $formatted = [];
723
+        foreach ($shares as $share) {
724
+            try {
725
+                $formatted[] = $this->formatShare($share, $path);
726
+            } catch (NotFoundException $e) {
727
+                //Ignore share
728
+            }
729
+        }
730
+
731
+        if ($include_tags) {
732
+            $formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
733
+        }
734
+
735
+        return new DataResponse($formatted);
736
+    }
737
+
738
+    /**
739
+     * @NoAdminRequired
740
+     *
741
+     * @param string $id
742
+     * @param int $permissions
743
+     * @param string $password
744
+     * @param string $sendPasswordByTalk
745
+     * @param string $publicUpload
746
+     * @param string $expireDate
747
+     * @param string $note
748
+     * @return DataResponse
749
+     * @throws LockedException
750
+     * @throws NotFoundException
751
+     * @throws OCSBadRequestException
752
+     * @throws OCSForbiddenException
753
+     * @throws OCSNotFoundException
754
+     */
755
+    public function updateShare(
756
+        string $id,
757
+        int $permissions = null,
758
+        string $password = null,
759
+        string $sendPasswordByTalk = null,
760
+        string $publicUpload = null,
761
+        string $expireDate = null,
762
+        string $note = null
763
+    ): DataResponse {
764
+        try {
765
+            $share = $this->getShareById($id);
766
+        } catch (ShareNotFound $e) {
767
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
768
+        }
769
+
770
+        $this->lock($share->getNode());
771
+
772
+        if (!$this->canAccessShare($share, false)) {
773
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
774
+        }
775
+
776
+        if ($permissions === null && $password === null && $sendPasswordByTalk === null && $publicUpload === null && $expireDate === null && $note === null) {
777
+            throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
778
+        }
779
+
780
+        if($note !== null) {
781
+            $share->setNote($note);
782
+        }
783
+
784
+        /*
785 785
 		 * expirationdate, password and publicUpload only make sense for link shares
786 786
 		 */
787
-		if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
788
-
789
-			$newPermissions = null;
790
-			if ($publicUpload === 'true') {
791
-				$newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
792
-			} else if ($publicUpload === 'false') {
793
-				$newPermissions = Constants::PERMISSION_READ;
794
-			}
795
-
796
-			if ($permissions !== null) {
797
-				$newPermissions = (int)$permissions;
798
-				$newPermissions = $newPermissions & ~Constants::PERMISSION_SHARE;
799
-			}
800
-
801
-			if ($newPermissions !== null &&
802
-				!in_array($newPermissions, [
803
-					Constants::PERMISSION_READ,
804
-					Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE, // legacy
805
-					Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE, // correct
806
-					Constants::PERMISSION_CREATE, // hidden file list
807
-					Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE, // allow to edit single files
808
-				], true)
809
-			) {
810
-				throw new OCSBadRequestException($this->l->t('Can\'t change permissions for public share links'));
811
-			}
812
-
813
-			if (
814
-				// legacy
815
-				$newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE) ||
816
-				// correct
817
-				$newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
818
-			) {
819
-				if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
820
-					throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
821
-				}
822
-
823
-				if (!($share->getNode() instanceof \OCP\Files\Folder)) {
824
-					throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders'));
825
-				}
826
-
827
-				// normalize to correct public upload permissions
828
-				$newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
829
-			}
830
-
831
-			if ($newPermissions !== null) {
832
-				$share->setPermissions($newPermissions);
833
-				$permissions = $newPermissions;
834
-			}
835
-
836
-			if ($expireDate === '') {
837
-				$share->setExpirationDate(null);
838
-			} else if ($expireDate !== null) {
839
-				try {
840
-					$expireDate = $this->parseDate($expireDate);
841
-				} catch (\Exception $e) {
842
-					throw new OCSBadRequestException($e->getMessage(), $e);
843
-				}
844
-				$share->setExpirationDate($expireDate);
845
-			}
846
-
847
-			if ($password === '') {
848
-				$share->setPassword(null);
849
-			} else if ($password !== null) {
850
-				$share->setPassword($password);
851
-			}
852
-
853
-		} else {
854
-			if ($permissions !== null) {
855
-				$permissions = (int)$permissions;
856
-				$share->setPermissions($permissions);
857
-			}
858
-
859
-			if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
860
-				if ($password === '') {
861
-					$share->setPassword(null);
862
-				} else if ($password !== null) {
863
-					$share->setPassword($password);
864
-				}
865
-
866
-				if ($sendPasswordByTalk === 'true') {
867
-					if (!$this->appManager->isEnabledForUser('spreed')) {
868
-						throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
869
-					}
870
-
871
-					$share->setSendPasswordByTalk(true);
872
-				} else {
873
-					$share->setSendPasswordByTalk(false);
874
-				}
875
-			}
876
-
877
-			if ($expireDate === '') {
878
-				$share->setExpirationDate(null);
879
-			} else if ($expireDate !== null) {
880
-				try {
881
-					$expireDate = $this->parseDate($expireDate);
882
-				} catch (\Exception $e) {
883
-					throw new OCSBadRequestException($e->getMessage(), $e);
884
-				}
885
-				$share->setExpirationDate($expireDate);
886
-			}
887
-
888
-		}
889
-
890
-		if ($permissions !== null && $share->getShareOwner() !== $this->currentUser) {
891
-			/* Check if this is an incomming share */
892
-			$incomingShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $share->getNode(), -1, 0);
893
-			$incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0));
894
-			$incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0));
895
-
896
-			/** @var \OCP\Share\IShare[] $incomingShares */
897
-			if (!empty($incomingShares)) {
898
-				$maxPermissions = 0;
899
-				foreach ($incomingShares as $incomingShare) {
900
-					$maxPermissions |= $incomingShare->getPermissions();
901
-				}
902
-
903
-				if ($share->getPermissions() & ~$maxPermissions) {
904
-					throw new OCSNotFoundException($this->l->t('Cannot increase permissions'));
905
-				}
906
-			}
907
-		}
908
-
909
-
910
-		try {
911
-			$share = $this->shareManager->updateShare($share);
912
-		} catch (\Exception $e) {
913
-			throw new OCSBadRequestException($e->getMessage(), $e);
914
-		}
915
-
916
-		return new DataResponse($this->formatShare($share));
917
-	}
918
-
919
-	/**
920
-	 * @suppress PhanUndeclaredClassMethod
921
-	 */
922
-	protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups = true): bool {
923
-		// A file with permissions 0 can't be accessed by us. So Don't show it
924
-		if ($share->getPermissions() === 0) {
925
-			return false;
926
-		}
927
-
928
-		// Owner of the file and the sharer of the file can always get share
929
-		if ($share->getShareOwner() === $this->currentUser ||
930
-			$share->getSharedBy() === $this->currentUser
931
-		) {
932
-			return true;
933
-		}
934
-
935
-		// If the share is shared with you (or a group you are a member of)
936
-		if ($share->getShareType() === Share::SHARE_TYPE_USER &&
937
-			$share->getSharedWith() === $this->currentUser
938
-		) {
939
-			return true;
940
-		}
941
-
942
-		if ($checkGroups && $share->getShareType() === Share::SHARE_TYPE_GROUP) {
943
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
944
-			$user = $this->userManager->get($this->currentUser);
945
-			if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
946
-				return true;
947
-			}
948
-		}
949
-
950
-		if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
951
-			// TODO: have a sanity check like above?
952
-			return true;
953
-		}
954
-
955
-		if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
956
-			try {
957
-				return $this->getRoomShareHelper()->canAccessShare($share, $this->currentUser);
958
-			} catch (QueryException $e) {
959
-				return false;
960
-			}
961
-		}
962
-
963
-		return false;
964
-	}
965
-
966
-	/**
967
-	 * Make sure that the passed date is valid ISO 8601
968
-	 * So YYYY-MM-DD
969
-	 * If not throw an exception
970
-	 *
971
-	 * @param string $expireDate
972
-	 *
973
-	 * @throws \Exception
974
-	 * @return \DateTime
975
-	 */
976
-	private function parseDate(string $expireDate): \DateTime {
977
-		try {
978
-			$date = new \DateTime($expireDate);
979
-		} catch (\Exception $e) {
980
-			throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
981
-		}
982
-
983
-		if ($date === false) {
984
-			throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
985
-		}
986
-
987
-		$date->setTime(0, 0, 0);
988
-
989
-		return $date;
990
-	}
991
-
992
-	/**
993
-	 * Since we have multiple providers but the OCS Share API v1 does
994
-	 * not support this we need to check all backends.
995
-	 *
996
-	 * @param string $id
997
-	 * @return \OCP\Share\IShare
998
-	 * @throws ShareNotFound
999
-	 */
1000
-	private function getShareById(string $id): IShare {
1001
-		$share = null;
1002
-
1003
-		// First check if it is an internal share.
1004
-		try {
1005
-			$share = $this->shareManager->getShareById('ocinternal:' . $id, $this->currentUser);
1006
-			return $share;
1007
-		} catch (ShareNotFound $e) {
1008
-			// Do nothing, just try the other share type
1009
-		}
1010
-
1011
-
1012
-		try {
1013
-			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
1014
-				$share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->currentUser);
1015
-				return $share;
1016
-			}
1017
-		} catch (ShareNotFound $e) {
1018
-			// Do nothing, just try the other share type
1019
-		}
1020
-
1021
-		try {
1022
-			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
1023
-				$share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->currentUser);
1024
-				return $share;
1025
-			}
1026
-		} catch (ShareNotFound $e) {
1027
-			// Do nothing, just try the other share type
1028
-		}
1029
-
1030
-		try {
1031
-			$share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->currentUser);
1032
-			return $share;
1033
-		} catch (ShareNotFound $e) {
1034
-			// Do nothing, just try the other share type
1035
-		}
1036
-
1037
-		if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
1038
-			throw new ShareNotFound();
1039
-		}
1040
-		$share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $this->currentUser);
1041
-
1042
-		return $share;
1043
-	}
1044
-
1045
-	/**
1046
-	 * Lock a Node
1047
-	 *
1048
-	 * @param \OCP\Files\Node $node
1049
-	 * @throws LockedException
1050
-	 */
1051
-	private function lock(\OCP\Files\Node $node) {
1052
-		$node->lock(ILockingProvider::LOCK_SHARED);
1053
-		$this->lockedNode = $node;
1054
-	}
1055
-
1056
-	/**
1057
-	 * Cleanup the remaining locks
1058
-	 * @throws @LockedException
1059
-	 */
1060
-	public function cleanup() {
1061
-		if ($this->lockedNode !== null) {
1062
-			$this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
1063
-		}
1064
-	}
1065
-
1066
-	/**
1067
-	 * Returns the helper of ShareAPIController for room shares.
1068
-	 *
1069
-	 * If the Talk application is not enabled or the helper is not available
1070
-	 * a QueryException is thrown instead.
1071
-	 *
1072
-	 * @return \OCA\Spreed\Share\Helper\ShareAPIController
1073
-	 * @throws QueryException
1074
-	 */
1075
-	private function getRoomShareHelper() {
1076
-		if (!$this->appManager->isEnabledForUser('spreed')) {
1077
-			throw new QueryException();
1078
-		}
1079
-
1080
-		return $this->serverContainer->query('\OCA\Spreed\Share\Helper\ShareAPIController');
1081
-	}
787
+        if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
788
+
789
+            $newPermissions = null;
790
+            if ($publicUpload === 'true') {
791
+                $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
792
+            } else if ($publicUpload === 'false') {
793
+                $newPermissions = Constants::PERMISSION_READ;
794
+            }
795
+
796
+            if ($permissions !== null) {
797
+                $newPermissions = (int)$permissions;
798
+                $newPermissions = $newPermissions & ~Constants::PERMISSION_SHARE;
799
+            }
800
+
801
+            if ($newPermissions !== null &&
802
+                !in_array($newPermissions, [
803
+                    Constants::PERMISSION_READ,
804
+                    Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE, // legacy
805
+                    Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE, // correct
806
+                    Constants::PERMISSION_CREATE, // hidden file list
807
+                    Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE, // allow to edit single files
808
+                ], true)
809
+            ) {
810
+                throw new OCSBadRequestException($this->l->t('Can\'t change permissions for public share links'));
811
+            }
812
+
813
+            if (
814
+                // legacy
815
+                $newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE) ||
816
+                // correct
817
+                $newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
818
+            ) {
819
+                if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
820
+                    throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
821
+                }
822
+
823
+                if (!($share->getNode() instanceof \OCP\Files\Folder)) {
824
+                    throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders'));
825
+                }
826
+
827
+                // normalize to correct public upload permissions
828
+                $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
829
+            }
830
+
831
+            if ($newPermissions !== null) {
832
+                $share->setPermissions($newPermissions);
833
+                $permissions = $newPermissions;
834
+            }
835
+
836
+            if ($expireDate === '') {
837
+                $share->setExpirationDate(null);
838
+            } else if ($expireDate !== null) {
839
+                try {
840
+                    $expireDate = $this->parseDate($expireDate);
841
+                } catch (\Exception $e) {
842
+                    throw new OCSBadRequestException($e->getMessage(), $e);
843
+                }
844
+                $share->setExpirationDate($expireDate);
845
+            }
846
+
847
+            if ($password === '') {
848
+                $share->setPassword(null);
849
+            } else if ($password !== null) {
850
+                $share->setPassword($password);
851
+            }
852
+
853
+        } else {
854
+            if ($permissions !== null) {
855
+                $permissions = (int)$permissions;
856
+                $share->setPermissions($permissions);
857
+            }
858
+
859
+            if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
860
+                if ($password === '') {
861
+                    $share->setPassword(null);
862
+                } else if ($password !== null) {
863
+                    $share->setPassword($password);
864
+                }
865
+
866
+                if ($sendPasswordByTalk === 'true') {
867
+                    if (!$this->appManager->isEnabledForUser('spreed')) {
868
+                        throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
869
+                    }
870
+
871
+                    $share->setSendPasswordByTalk(true);
872
+                } else {
873
+                    $share->setSendPasswordByTalk(false);
874
+                }
875
+            }
876
+
877
+            if ($expireDate === '') {
878
+                $share->setExpirationDate(null);
879
+            } else if ($expireDate !== null) {
880
+                try {
881
+                    $expireDate = $this->parseDate($expireDate);
882
+                } catch (\Exception $e) {
883
+                    throw new OCSBadRequestException($e->getMessage(), $e);
884
+                }
885
+                $share->setExpirationDate($expireDate);
886
+            }
887
+
888
+        }
889
+
890
+        if ($permissions !== null && $share->getShareOwner() !== $this->currentUser) {
891
+            /* Check if this is an incomming share */
892
+            $incomingShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $share->getNode(), -1, 0);
893
+            $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0));
894
+            $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0));
895
+
896
+            /** @var \OCP\Share\IShare[] $incomingShares */
897
+            if (!empty($incomingShares)) {
898
+                $maxPermissions = 0;
899
+                foreach ($incomingShares as $incomingShare) {
900
+                    $maxPermissions |= $incomingShare->getPermissions();
901
+                }
902
+
903
+                if ($share->getPermissions() & ~$maxPermissions) {
904
+                    throw new OCSNotFoundException($this->l->t('Cannot increase permissions'));
905
+                }
906
+            }
907
+        }
908
+
909
+
910
+        try {
911
+            $share = $this->shareManager->updateShare($share);
912
+        } catch (\Exception $e) {
913
+            throw new OCSBadRequestException($e->getMessage(), $e);
914
+        }
915
+
916
+        return new DataResponse($this->formatShare($share));
917
+    }
918
+
919
+    /**
920
+     * @suppress PhanUndeclaredClassMethod
921
+     */
922
+    protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups = true): bool {
923
+        // A file with permissions 0 can't be accessed by us. So Don't show it
924
+        if ($share->getPermissions() === 0) {
925
+            return false;
926
+        }
927
+
928
+        // Owner of the file and the sharer of the file can always get share
929
+        if ($share->getShareOwner() === $this->currentUser ||
930
+            $share->getSharedBy() === $this->currentUser
931
+        ) {
932
+            return true;
933
+        }
934
+
935
+        // If the share is shared with you (or a group you are a member of)
936
+        if ($share->getShareType() === Share::SHARE_TYPE_USER &&
937
+            $share->getSharedWith() === $this->currentUser
938
+        ) {
939
+            return true;
940
+        }
941
+
942
+        if ($checkGroups && $share->getShareType() === Share::SHARE_TYPE_GROUP) {
943
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
944
+            $user = $this->userManager->get($this->currentUser);
945
+            if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
946
+                return true;
947
+            }
948
+        }
949
+
950
+        if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
951
+            // TODO: have a sanity check like above?
952
+            return true;
953
+        }
954
+
955
+        if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
956
+            try {
957
+                return $this->getRoomShareHelper()->canAccessShare($share, $this->currentUser);
958
+            } catch (QueryException $e) {
959
+                return false;
960
+            }
961
+        }
962
+
963
+        return false;
964
+    }
965
+
966
+    /**
967
+     * Make sure that the passed date is valid ISO 8601
968
+     * So YYYY-MM-DD
969
+     * If not throw an exception
970
+     *
971
+     * @param string $expireDate
972
+     *
973
+     * @throws \Exception
974
+     * @return \DateTime
975
+     */
976
+    private function parseDate(string $expireDate): \DateTime {
977
+        try {
978
+            $date = new \DateTime($expireDate);
979
+        } catch (\Exception $e) {
980
+            throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
981
+        }
982
+
983
+        if ($date === false) {
984
+            throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
985
+        }
986
+
987
+        $date->setTime(0, 0, 0);
988
+
989
+        return $date;
990
+    }
991
+
992
+    /**
993
+     * Since we have multiple providers but the OCS Share API v1 does
994
+     * not support this we need to check all backends.
995
+     *
996
+     * @param string $id
997
+     * @return \OCP\Share\IShare
998
+     * @throws ShareNotFound
999
+     */
1000
+    private function getShareById(string $id): IShare {
1001
+        $share = null;
1002
+
1003
+        // First check if it is an internal share.
1004
+        try {
1005
+            $share = $this->shareManager->getShareById('ocinternal:' . $id, $this->currentUser);
1006
+            return $share;
1007
+        } catch (ShareNotFound $e) {
1008
+            // Do nothing, just try the other share type
1009
+        }
1010
+
1011
+
1012
+        try {
1013
+            if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
1014
+                $share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->currentUser);
1015
+                return $share;
1016
+            }
1017
+        } catch (ShareNotFound $e) {
1018
+            // Do nothing, just try the other share type
1019
+        }
1020
+
1021
+        try {
1022
+            if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
1023
+                $share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->currentUser);
1024
+                return $share;
1025
+            }
1026
+        } catch (ShareNotFound $e) {
1027
+            // Do nothing, just try the other share type
1028
+        }
1029
+
1030
+        try {
1031
+            $share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->currentUser);
1032
+            return $share;
1033
+        } catch (ShareNotFound $e) {
1034
+            // Do nothing, just try the other share type
1035
+        }
1036
+
1037
+        if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
1038
+            throw new ShareNotFound();
1039
+        }
1040
+        $share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $this->currentUser);
1041
+
1042
+        return $share;
1043
+    }
1044
+
1045
+    /**
1046
+     * Lock a Node
1047
+     *
1048
+     * @param \OCP\Files\Node $node
1049
+     * @throws LockedException
1050
+     */
1051
+    private function lock(\OCP\Files\Node $node) {
1052
+        $node->lock(ILockingProvider::LOCK_SHARED);
1053
+        $this->lockedNode = $node;
1054
+    }
1055
+
1056
+    /**
1057
+     * Cleanup the remaining locks
1058
+     * @throws @LockedException
1059
+     */
1060
+    public function cleanup() {
1061
+        if ($this->lockedNode !== null) {
1062
+            $this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
1063
+        }
1064
+    }
1065
+
1066
+    /**
1067
+     * Returns the helper of ShareAPIController for room shares.
1068
+     *
1069
+     * If the Talk application is not enabled or the helper is not available
1070
+     * a QueryException is thrown instead.
1071
+     *
1072
+     * @return \OCA\Spreed\Share\Helper\ShareAPIController
1073
+     * @throws QueryException
1074
+     */
1075
+    private function getRoomShareHelper() {
1076
+        if (!$this->appManager->isEnabledForUser('spreed')) {
1077
+            throw new QueryException();
1078
+        }
1079
+
1080
+        return $this->serverContainer->query('\OCA\Spreed\Share\Helper\ShareAPIController');
1081
+    }
1082 1082
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -231,14 +231,14 @@  discard block
 block discarded – undo
231 231
 
232 232
 			$result['share_with_displayname'] = $share->getSharedWithDisplayName();
233 233
 			if (empty($result['share_with_displayname'])) {
234
-				$displayNameLength = ($hasCircleId? strrpos($share->getSharedWith(), ' '): strlen($share->getSharedWith()));
234
+				$displayNameLength = ($hasCircleId ? strrpos($share->getSharedWith(), ' ') : strlen($share->getSharedWith()));
235 235
 				$result['share_with_displayname'] = substr($share->getSharedWith(), 0, $displayNameLength);
236 236
 			}
237 237
 
238 238
 			$result['share_with_avatar'] = $share->getSharedWithAvatar();
239 239
 
240
-			$shareWithStart = ($hasCircleId? strrpos($share->getSharedWith(), '[') + 1: 0);
241
-			$shareWithLength = ($hasCircleId? -1: strpos($share->getSharedWith(), ' '));
240
+			$shareWithStart = ($hasCircleId ? strrpos($share->getSharedWith(), '[') + 1 : 0);
241
+			$shareWithLength = ($hasCircleId ? -1 : strpos($share->getSharedWith(), ' '));
242 242
 			$result['share_with'] = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
243 243
 		} else if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
244 244
 			$result['share_with'] = $share->getSharedWith();
@@ -268,7 +268,7 @@  discard block
 block discarded – undo
268 268
 		// FIXME: If we inject the contacts manager it gets initialized bofore any address books are registered
269 269
 		$result = \OC::$server->getContactsManager()->search($query, [$property]);
270 270
 		foreach ($result as $r) {
271
-			foreach($r[$property] as $value) {
271
+			foreach ($r[$property] as $value) {
272 272
 				if ($value === $query) {
273 273
 					return $r['FN'];
274 274
 				}
@@ -498,7 +498,7 @@  discard block
 block discarded – undo
498 498
 
499 499
 			$share->setSharedWith($shareWith);
500 500
 			$share->setPermissions($permissions);
501
-		}  else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) {
501
+		} else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) {
502 502
 			if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
503 503
 				throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
504 504
 			}
@@ -574,7 +574,7 @@  discard block
 block discarded – undo
574 574
 
575 575
 		$shares = array_merge($userShares, $groupShares, $circleShares, $roomShares);
576 576
 
577
-		$shares = array_filter($shares, function (IShare $share) {
577
+		$shares = array_filter($shares, function(IShare $share) {
578 578
 			return $share->getShareOwner() !== $this->currentUser;
579 579
 		});
580 580
 
@@ -613,7 +613,7 @@  discard block
 block discarded – undo
613 613
 			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $node, false, -1, 0));
614 614
 			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $node, false, -1, 0));
615 615
 			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $node, false, -1, 0));
616
-			if($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
616
+			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
617 617
 				$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $node, false, -1, 0));
618 618
 			}
619 619
 			if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
@@ -777,7 +777,7 @@  discard block
 block discarded – undo
777 777
 			throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
778 778
 		}
779 779
 
780
-		if($note !== null) {
780
+		if ($note !== null) {
781 781
 			$share->setNote($note);
782 782
 		}
783 783
 
@@ -794,7 +794,7 @@  discard block
 block discarded – undo
794 794
 			}
795 795
 
796 796
 			if ($permissions !== null) {
797
-				$newPermissions = (int)$permissions;
797
+				$newPermissions = (int) $permissions;
798 798
 				$newPermissions = $newPermissions & ~Constants::PERMISSION_SHARE;
799 799
 			}
800 800
 
@@ -852,7 +852,7 @@  discard block
 block discarded – undo
852 852
 
853 853
 		} else {
854 854
 			if ($permissions !== null) {
855
-				$permissions = (int)$permissions;
855
+				$permissions = (int) $permissions;
856 856
 				$share->setPermissions($permissions);
857 857
 			}
858 858
 
@@ -1002,7 +1002,7 @@  discard block
 block discarded – undo
1002 1002
 
1003 1003
 		// First check if it is an internal share.
1004 1004
 		try {
1005
-			$share = $this->shareManager->getShareById('ocinternal:' . $id, $this->currentUser);
1005
+			$share = $this->shareManager->getShareById('ocinternal:'.$id, $this->currentUser);
1006 1006
 			return $share;
1007 1007
 		} catch (ShareNotFound $e) {
1008 1008
 			// Do nothing, just try the other share type
@@ -1011,7 +1011,7 @@  discard block
 block discarded – undo
1011 1011
 
1012 1012
 		try {
1013 1013
 			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
1014
-				$share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->currentUser);
1014
+				$share = $this->shareManager->getShareById('ocCircleShare:'.$id, $this->currentUser);
1015 1015
 				return $share;
1016 1016
 			}
1017 1017
 		} catch (ShareNotFound $e) {
@@ -1020,7 +1020,7 @@  discard block
 block discarded – undo
1020 1020
 
1021 1021
 		try {
1022 1022
 			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
1023
-				$share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->currentUser);
1023
+				$share = $this->shareManager->getShareById('ocMailShare:'.$id, $this->currentUser);
1024 1024
 				return $share;
1025 1025
 			}
1026 1026
 		} catch (ShareNotFound $e) {
@@ -1028,7 +1028,7 @@  discard block
 block discarded – undo
1028 1028
 		}
1029 1029
 
1030 1030
 		try {
1031
-			$share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->currentUser);
1031
+			$share = $this->shareManager->getShareById('ocRoomShare:'.$id, $this->currentUser);
1032 1032
 			return $share;
1033 1033
 		} catch (ShareNotFound $e) {
1034 1034
 			// Do nothing, just try the other share type
@@ -1037,7 +1037,7 @@  discard block
 block discarded – undo
1037 1037
 		if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
1038 1038
 			throw new ShareNotFound();
1039 1039
 		}
1040
-		$share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $this->currentUser);
1040
+		$share = $this->shareManager->getShareById('ocFederatedSharing:'.$id, $this->currentUser);
1041 1041
 
1042 1042
 		return $share;
1043 1043
 	}
Please login to merge, or discard this patch.
Braces   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -498,7 +498,7 @@
 block discarded – undo
498 498
 
499 499
 			$share->setSharedWith($shareWith);
500 500
 			$share->setPermissions($permissions);
501
-		}  else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) {
501
+		} else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) {
502 502
 			if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
503 503
 				throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
504 504
 			}
Please login to merge, or discard this patch.
lib/public/Federation/Exceptions/ProviderAlreadyExistsException.php 2 patches
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -32,19 +32,19 @@
 block discarded – undo
32 32
  */
33 33
 class ProviderAlreadyExistsException extends HintException {
34 34
 
35
-	/**
36
-	 * ProviderAlreadyExistsException constructor.
37
-	 *
38
-	 * @since 14.0.0
39
-	 *
40
-	 * @param string $newProviderId cloud federation provider ID of the new provider
41
-	 * @param string $existingProviderName name of cloud federation provider which already use the same ID
42
-	 */
43
-	public function __construct($newProviderId, $existingProviderName) {
44
-		$l = \OC::$server->getL10N('federation');
45
-		$message = 'ID "' . $newProviderId . '" already used by cloud federation provider "' . $existingProviderName . '"';
46
-		$hint = $l->t('ID "%1$s" already used by cloud federation provider "%2$s"', [$newProviderId, $existingProviderName]);
47
-		parent::__construct($message, $hint);
48
-	}
35
+    /**
36
+     * ProviderAlreadyExistsException constructor.
37
+     *
38
+     * @since 14.0.0
39
+     *
40
+     * @param string $newProviderId cloud federation provider ID of the new provider
41
+     * @param string $existingProviderName name of cloud federation provider which already use the same ID
42
+     */
43
+    public function __construct($newProviderId, $existingProviderName) {
44
+        $l = \OC::$server->getL10N('federation');
45
+        $message = 'ID "' . $newProviderId . '" already used by cloud federation provider "' . $existingProviderName . '"';
46
+        $hint = $l->t('ID "%1$s" already used by cloud federation provider "%2$s"', [$newProviderId, $existingProviderName]);
47
+        parent::__construct($message, $hint);
48
+    }
49 49
 
50 50
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -42,7 +42,7 @@
 block discarded – undo
42 42
 	 */
43 43
 	public function __construct($newProviderId, $existingProviderName) {
44 44
 		$l = \OC::$server->getL10N('federation');
45
-		$message = 'ID "' . $newProviderId . '" already used by cloud federation provider "' . $existingProviderName . '"';
45
+		$message = 'ID "'.$newProviderId.'" already used by cloud federation provider "'.$existingProviderName.'"';
46 46
 		$hint = $l->t('ID "%1$s" already used by cloud federation provider "%2$s"', [$newProviderId, $existingProviderName]);
47 47
 		parent::__construct($message, $hint);
48 48
 	}
Please login to merge, or discard this patch.
lib/private/App/DependencyAnalyzer.php 2 patches
Indentation   +298 added lines, -298 removed lines patch added patch discarded remove patch
@@ -33,326 +33,326 @@
 block discarded – undo
33 33
 
34 34
 class DependencyAnalyzer {
35 35
 
36
-	/** @var Platform */
37
-	private $platform;
38
-	/** @var \OCP\IL10N */
39
-	private $l;
40
-	/** @var array */
41
-	private $appInfo;
36
+    /** @var Platform */
37
+    private $platform;
38
+    /** @var \OCP\IL10N */
39
+    private $l;
40
+    /** @var array */
41
+    private $appInfo;
42 42
 
43
-	/**
44
-	 * @param Platform $platform
45
-	 * @param \OCP\IL10N $l
46
-	 */
47
-	public function __construct(Platform $platform, IL10N $l) {
48
-		$this->platform = $platform;
49
-		$this->l = $l;
50
-	}
43
+    /**
44
+     * @param Platform $platform
45
+     * @param \OCP\IL10N $l
46
+     */
47
+    public function __construct(Platform $platform, IL10N $l) {
48
+        $this->platform = $platform;
49
+        $this->l = $l;
50
+    }
51 51
 
52
-	/**
53
-	 * @param array $app
54
-	 * @returns array of missing dependencies
55
-	 */
56
-	public function analyze(array $app) {
57
-		$this->appInfo = $app;
58
-		if (isset($app['dependencies'])) {
59
-			$dependencies = $app['dependencies'];
60
-		} else {
61
-			$dependencies = [];
62
-		}
52
+    /**
53
+     * @param array $app
54
+     * @returns array of missing dependencies
55
+     */
56
+    public function analyze(array $app) {
57
+        $this->appInfo = $app;
58
+        if (isset($app['dependencies'])) {
59
+            $dependencies = $app['dependencies'];
60
+        } else {
61
+            $dependencies = [];
62
+        }
63 63
 
64
-		return array_merge(
65
-			$this->analyzePhpVersion($dependencies),
66
-			$this->analyzeDatabases($dependencies),
67
-			$this->analyzeCommands($dependencies),
68
-			$this->analyzeLibraries($dependencies),
69
-			$this->analyzeOS($dependencies),
70
-			$this->analyzeOC($dependencies, $app)
71
-		);
72
-	}
64
+        return array_merge(
65
+            $this->analyzePhpVersion($dependencies),
66
+            $this->analyzeDatabases($dependencies),
67
+            $this->analyzeCommands($dependencies),
68
+            $this->analyzeLibraries($dependencies),
69
+            $this->analyzeOS($dependencies),
70
+            $this->analyzeOC($dependencies, $app)
71
+        );
72
+    }
73 73
 
74
-	/**
75
-	 * Truncates both versions to the lowest common version, e.g.
76
-	 * 5.1.2.3 and 5.1 will be turned into 5.1 and 5.1,
77
-	 * 5.2.6.5 and 5.1 will be turned into 5.2 and 5.1
78
-	 * @param string $first
79
-	 * @param string $second
80
-	 * @return string[] first element is the first version, second element is the
81
-	 * second version
82
-	 */
83
-	private function normalizeVersions($first, $second) {
84
-		$first = explode('.', $first);
85
-		$second = explode('.', $second);
74
+    /**
75
+     * Truncates both versions to the lowest common version, e.g.
76
+     * 5.1.2.3 and 5.1 will be turned into 5.1 and 5.1,
77
+     * 5.2.6.5 and 5.1 will be turned into 5.2 and 5.1
78
+     * @param string $first
79
+     * @param string $second
80
+     * @return string[] first element is the first version, second element is the
81
+     * second version
82
+     */
83
+    private function normalizeVersions($first, $second) {
84
+        $first = explode('.', $first);
85
+        $second = explode('.', $second);
86 86
 
87
-		// get both arrays to the same minimum size
88
-		$length = min(count($second), count($first));
89
-		$first = array_slice($first, 0, $length);
90
-		$second = array_slice($second, 0, $length);
87
+        // get both arrays to the same minimum size
88
+        $length = min(count($second), count($first));
89
+        $first = array_slice($first, 0, $length);
90
+        $second = array_slice($second, 0, $length);
91 91
 
92
-		return [implode('.', $first), implode('.', $second)];
93
-	}
92
+        return [implode('.', $first), implode('.', $second)];
93
+    }
94 94
 
95
-	/**
96
-	 * Parameters will be normalized and then passed into version_compare
97
-	 * in the same order they are specified in the method header
98
-	 * @param string $first
99
-	 * @param string $second
100
-	 * @param string $operator
101
-	 * @return bool result similar to version_compare
102
-	 */
103
-	private function compare($first, $second, $operator) {
104
-		// we can't normalize versions if one of the given parameters is not a
105
-		// version string but null. In case one parameter is null normalization
106
-		// will therefore be skipped
107
-		if ($first !== null && $second !== null) {
108
-			list($first, $second) = $this->normalizeVersions($first, $second);
109
-		}
95
+    /**
96
+     * Parameters will be normalized and then passed into version_compare
97
+     * in the same order they are specified in the method header
98
+     * @param string $first
99
+     * @param string $second
100
+     * @param string $operator
101
+     * @return bool result similar to version_compare
102
+     */
103
+    private function compare($first, $second, $operator) {
104
+        // we can't normalize versions if one of the given parameters is not a
105
+        // version string but null. In case one parameter is null normalization
106
+        // will therefore be skipped
107
+        if ($first !== null && $second !== null) {
108
+            list($first, $second) = $this->normalizeVersions($first, $second);
109
+        }
110 110
 
111
-		return version_compare($first, $second, $operator);
112
-	}
111
+        return version_compare($first, $second, $operator);
112
+    }
113 113
 
114
-	/**
115
-	 * Checks if a version is bigger than another version
116
-	 * @param string $first
117
-	 * @param string $second
118
-	 * @return bool true if the first version is bigger than the second
119
-	 */
120
-	private function compareBigger($first, $second) {
121
-		return $this->compare($first, $second, '>');
122
-	}
114
+    /**
115
+     * Checks if a version is bigger than another version
116
+     * @param string $first
117
+     * @param string $second
118
+     * @return bool true if the first version is bigger than the second
119
+     */
120
+    private function compareBigger($first, $second) {
121
+        return $this->compare($first, $second, '>');
122
+    }
123 123
 
124
-	/**
125
-	 * Checks if a version is smaller than another version
126
-	 * @param string $first
127
-	 * @param string $second
128
-	 * @return bool true if the first version is smaller than the second
129
-	 */
130
-	private function compareSmaller($first, $second) {
131
-		return $this->compare($first, $second, '<');
132
-	}
124
+    /**
125
+     * Checks if a version is smaller than another version
126
+     * @param string $first
127
+     * @param string $second
128
+     * @return bool true if the first version is smaller than the second
129
+     */
130
+    private function compareSmaller($first, $second) {
131
+        return $this->compare($first, $second, '<');
132
+    }
133 133
 
134
-	/**
135
-	 * @param array $dependencies
136
-	 * @return array
137
-	 */
138
-	private function analyzePhpVersion(array $dependencies) {
139
-		$missing = [];
140
-		if (isset($dependencies['php']['@attributes']['min-version'])) {
141
-			$minVersion = $dependencies['php']['@attributes']['min-version'];
142
-			if ($this->compareSmaller($this->platform->getPhpVersion(), $minVersion)) {
143
-				$missing[] = (string)$this->l->t('PHP %s or higher is required.', [$minVersion]);
144
-			}
145
-		}
146
-		if (isset($dependencies['php']['@attributes']['max-version'])) {
147
-			$maxVersion = $dependencies['php']['@attributes']['max-version'];
148
-			if ($this->compareBigger($this->platform->getPhpVersion(), $maxVersion)) {
149
-				$missing[] = (string)$this->l->t('PHP with a version lower than %s is required.', [$maxVersion]);
150
-			}
151
-		}
152
-		if (isset($dependencies['php']['@attributes']['min-int-size'])) {
153
-			$intSize = $dependencies['php']['@attributes']['min-int-size'];
154
-			if ($intSize > $this->platform->getIntSize()*8) {
155
-				$missing[] = (string)$this->l->t('%sbit or higher PHP required.', [$intSize]);
156
-			}
157
-		}
158
-		return $missing;
159
-	}
134
+    /**
135
+     * @param array $dependencies
136
+     * @return array
137
+     */
138
+    private function analyzePhpVersion(array $dependencies) {
139
+        $missing = [];
140
+        if (isset($dependencies['php']['@attributes']['min-version'])) {
141
+            $minVersion = $dependencies['php']['@attributes']['min-version'];
142
+            if ($this->compareSmaller($this->platform->getPhpVersion(), $minVersion)) {
143
+                $missing[] = (string)$this->l->t('PHP %s or higher is required.', [$minVersion]);
144
+            }
145
+        }
146
+        if (isset($dependencies['php']['@attributes']['max-version'])) {
147
+            $maxVersion = $dependencies['php']['@attributes']['max-version'];
148
+            if ($this->compareBigger($this->platform->getPhpVersion(), $maxVersion)) {
149
+                $missing[] = (string)$this->l->t('PHP with a version lower than %s is required.', [$maxVersion]);
150
+            }
151
+        }
152
+        if (isset($dependencies['php']['@attributes']['min-int-size'])) {
153
+            $intSize = $dependencies['php']['@attributes']['min-int-size'];
154
+            if ($intSize > $this->platform->getIntSize()*8) {
155
+                $missing[] = (string)$this->l->t('%sbit or higher PHP required.', [$intSize]);
156
+            }
157
+        }
158
+        return $missing;
159
+    }
160 160
 
161
-	/**
162
-	 * @param array $dependencies
163
-	 * @return array
164
-	 */
165
-	private function analyzeDatabases(array $dependencies) {
166
-		$missing = [];
167
-		if (!isset($dependencies['database'])) {
168
-			return $missing;
169
-		}
161
+    /**
162
+     * @param array $dependencies
163
+     * @return array
164
+     */
165
+    private function analyzeDatabases(array $dependencies) {
166
+        $missing = [];
167
+        if (!isset($dependencies['database'])) {
168
+            return $missing;
169
+        }
170 170
 
171
-		$supportedDatabases = $dependencies['database'];
172
-		if (empty($supportedDatabases)) {
173
-			return $missing;
174
-		}
175
-		if (!is_array($supportedDatabases)) {
176
-			$supportedDatabases = array($supportedDatabases);
177
-		}
178
-		$supportedDatabases = array_map(function ($db) {
179
-			return $this->getValue($db);
180
-		}, $supportedDatabases);
181
-		$currentDatabase = $this->platform->getDatabase();
182
-		if (!in_array($currentDatabase, $supportedDatabases)) {
183
-			$missing[] = (string)$this->l->t('Following databases are supported: %s', [implode(', ', $supportedDatabases)]);
184
-		}
185
-		return $missing;
186
-	}
171
+        $supportedDatabases = $dependencies['database'];
172
+        if (empty($supportedDatabases)) {
173
+            return $missing;
174
+        }
175
+        if (!is_array($supportedDatabases)) {
176
+            $supportedDatabases = array($supportedDatabases);
177
+        }
178
+        $supportedDatabases = array_map(function ($db) {
179
+            return $this->getValue($db);
180
+        }, $supportedDatabases);
181
+        $currentDatabase = $this->platform->getDatabase();
182
+        if (!in_array($currentDatabase, $supportedDatabases)) {
183
+            $missing[] = (string)$this->l->t('Following databases are supported: %s', [implode(', ', $supportedDatabases)]);
184
+        }
185
+        return $missing;
186
+    }
187 187
 
188
-	/**
189
-	 * @param array $dependencies
190
-	 * @return array
191
-	 */
192
-	private function analyzeCommands(array $dependencies) {
193
-		$missing = [];
194
-		if (!isset($dependencies['command'])) {
195
-			return $missing;
196
-		}
188
+    /**
189
+     * @param array $dependencies
190
+     * @return array
191
+     */
192
+    private function analyzeCommands(array $dependencies) {
193
+        $missing = [];
194
+        if (!isset($dependencies['command'])) {
195
+            return $missing;
196
+        }
197 197
 
198
-		$commands = $dependencies['command'];
199
-		if (!is_array($commands)) {
200
-			$commands = array($commands);
201
-		}
202
-		if (isset($commands['@value'])) {
203
-			$commands = [$commands];
204
-		}
205
-		$os = $this->platform->getOS();
206
-		foreach ($commands as $command) {
207
-			if (isset($command['@attributes']['os']) && $command['@attributes']['os'] !== $os) {
208
-				continue;
209
-			}
210
-			$commandName = $this->getValue($command);
211
-			if (!$this->platform->isCommandKnown($commandName)) {
212
-				$missing[] = (string)$this->l->t('The command line tool %s could not be found', [$commandName]);
213
-			}
214
-		}
215
-		return $missing;
216
-	}
198
+        $commands = $dependencies['command'];
199
+        if (!is_array($commands)) {
200
+            $commands = array($commands);
201
+        }
202
+        if (isset($commands['@value'])) {
203
+            $commands = [$commands];
204
+        }
205
+        $os = $this->platform->getOS();
206
+        foreach ($commands as $command) {
207
+            if (isset($command['@attributes']['os']) && $command['@attributes']['os'] !== $os) {
208
+                continue;
209
+            }
210
+            $commandName = $this->getValue($command);
211
+            if (!$this->platform->isCommandKnown($commandName)) {
212
+                $missing[] = (string)$this->l->t('The command line tool %s could not be found', [$commandName]);
213
+            }
214
+        }
215
+        return $missing;
216
+    }
217 217
 
218
-	/**
219
-	 * @param array $dependencies
220
-	 * @return array
221
-	 */
222
-	private function analyzeLibraries(array $dependencies) {
223
-		$missing = [];
224
-		if (!isset($dependencies['lib'])) {
225
-			return $missing;
226
-		}
218
+    /**
219
+     * @param array $dependencies
220
+     * @return array
221
+     */
222
+    private function analyzeLibraries(array $dependencies) {
223
+        $missing = [];
224
+        if (!isset($dependencies['lib'])) {
225
+            return $missing;
226
+        }
227 227
 
228
-		$libs = $dependencies['lib'];
229
-		if (!is_array($libs)) {
230
-			$libs = array($libs);
231
-		}
232
-		if (isset($libs['@value'])) {
233
-			$libs = [$libs];
234
-		}
235
-		foreach ($libs as $lib) {
236
-			$libName = $this->getValue($lib);
237
-			$libVersion = $this->platform->getLibraryVersion($libName);
238
-			if (is_null($libVersion)) {
239
-				$missing[] = $this->l->t('The library %s is not available.', [$libName]);
240
-				continue;
241
-			}
228
+        $libs = $dependencies['lib'];
229
+        if (!is_array($libs)) {
230
+            $libs = array($libs);
231
+        }
232
+        if (isset($libs['@value'])) {
233
+            $libs = [$libs];
234
+        }
235
+        foreach ($libs as $lib) {
236
+            $libName = $this->getValue($lib);
237
+            $libVersion = $this->platform->getLibraryVersion($libName);
238
+            if (is_null($libVersion)) {
239
+                $missing[] = $this->l->t('The library %s is not available.', [$libName]);
240
+                continue;
241
+            }
242 242
 
243
-			if (is_array($lib)) {
244
-				if (isset($lib['@attributes']['min-version'])) {
245
-					$minVersion = $lib['@attributes']['min-version'];
246
-					if ($this->compareSmaller($libVersion, $minVersion)) {
247
-						$missing[] = $this->l->t('Library %1$s with a version higher than %2$s is required - available version %3$s.',
248
-							[$libName, $minVersion, $libVersion]);
249
-					}
250
-				}
251
-				if (isset($lib['@attributes']['max-version'])) {
252
-					$maxVersion = $lib['@attributes']['max-version'];
253
-					if ($this->compareBigger($libVersion, $maxVersion)) {
254
-						$missing[] = $this->l->t('Library %1$s with a version lower than %2$s is required - available version %3$s.',
255
-							[$libName, $maxVersion, $libVersion]);
256
-					}
257
-				}
258
-			}
259
-		}
260
-		return $missing;
261
-	}
243
+            if (is_array($lib)) {
244
+                if (isset($lib['@attributes']['min-version'])) {
245
+                    $minVersion = $lib['@attributes']['min-version'];
246
+                    if ($this->compareSmaller($libVersion, $minVersion)) {
247
+                        $missing[] = $this->l->t('Library %1$s with a version higher than %2$s is required - available version %3$s.',
248
+                            [$libName, $minVersion, $libVersion]);
249
+                    }
250
+                }
251
+                if (isset($lib['@attributes']['max-version'])) {
252
+                    $maxVersion = $lib['@attributes']['max-version'];
253
+                    if ($this->compareBigger($libVersion, $maxVersion)) {
254
+                        $missing[] = $this->l->t('Library %1$s with a version lower than %2$s is required - available version %3$s.',
255
+                            [$libName, $maxVersion, $libVersion]);
256
+                    }
257
+                }
258
+            }
259
+        }
260
+        return $missing;
261
+    }
262 262
 
263
-	/**
264
-	 * @param array $dependencies
265
-	 * @return array
266
-	 */
267
-	private function analyzeOS(array $dependencies) {
268
-		$missing = [];
269
-		if (!isset($dependencies['os'])) {
270
-			return $missing;
271
-		}
263
+    /**
264
+     * @param array $dependencies
265
+     * @return array
266
+     */
267
+    private function analyzeOS(array $dependencies) {
268
+        $missing = [];
269
+        if (!isset($dependencies['os'])) {
270
+            return $missing;
271
+        }
272 272
 
273
-		$oss = $dependencies['os'];
274
-		if (empty($oss)) {
275
-			return $missing;
276
-		}
277
-		if (is_array($oss)) {
278
-			$oss = array_map(function ($os) {
279
-				return $this->getValue($os);
280
-			}, $oss);
281
-		} else {
282
-			$oss = array($oss);
283
-		}
284
-		$currentOS = $this->platform->getOS();
285
-		if (!in_array($currentOS, $oss)) {
286
-			$missing[] = (string)$this->l->t('Following platforms are supported: %s', [implode(', ', $oss)]);
287
-		}
288
-		return $missing;
289
-	}
273
+        $oss = $dependencies['os'];
274
+        if (empty($oss)) {
275
+            return $missing;
276
+        }
277
+        if (is_array($oss)) {
278
+            $oss = array_map(function ($os) {
279
+                return $this->getValue($os);
280
+            }, $oss);
281
+        } else {
282
+            $oss = array($oss);
283
+        }
284
+        $currentOS = $this->platform->getOS();
285
+        if (!in_array($currentOS, $oss)) {
286
+            $missing[] = (string)$this->l->t('Following platforms are supported: %s', [implode(', ', $oss)]);
287
+        }
288
+        return $missing;
289
+    }
290 290
 
291
-	/**
292
-	 * @param array $dependencies
293
-	 * @param array $appInfo
294
-	 * @return array
295
-	 */
296
-	private function analyzeOC(array $dependencies, array $appInfo) {
297
-		$missing = [];
298
-		$minVersion = null;
299
-		if (isset($dependencies['nextcloud']['@attributes']['min-version'])) {
300
-			$minVersion = $dependencies['nextcloud']['@attributes']['min-version'];
301
-		} elseif (isset($dependencies['owncloud']['@attributes']['min-version'])) {
302
-			$minVersion = $dependencies['owncloud']['@attributes']['min-version'];
303
-		} elseif (isset($appInfo['requiremin'])) {
304
-			$minVersion = $appInfo['requiremin'];
305
-		} elseif (isset($appInfo['require'])) {
306
-			$minVersion = $appInfo['require'];
307
-		}
308
-		$maxVersion = null;
309
-		if (isset($dependencies['nextcloud']['@attributes']['max-version'])) {
310
-			$maxVersion = $dependencies['nextcloud']['@attributes']['max-version'];
311
-		} elseif (isset($dependencies['owncloud']['@attributes']['max-version'])) {
312
-			$maxVersion = $dependencies['owncloud']['@attributes']['max-version'];
313
-		} elseif (isset($appInfo['requiremax'])) {
314
-			$maxVersion = $appInfo['requiremax'];
315
-		}
291
+    /**
292
+     * @param array $dependencies
293
+     * @param array $appInfo
294
+     * @return array
295
+     */
296
+    private function analyzeOC(array $dependencies, array $appInfo) {
297
+        $missing = [];
298
+        $minVersion = null;
299
+        if (isset($dependencies['nextcloud']['@attributes']['min-version'])) {
300
+            $minVersion = $dependencies['nextcloud']['@attributes']['min-version'];
301
+        } elseif (isset($dependencies['owncloud']['@attributes']['min-version'])) {
302
+            $minVersion = $dependencies['owncloud']['@attributes']['min-version'];
303
+        } elseif (isset($appInfo['requiremin'])) {
304
+            $minVersion = $appInfo['requiremin'];
305
+        } elseif (isset($appInfo['require'])) {
306
+            $minVersion = $appInfo['require'];
307
+        }
308
+        $maxVersion = null;
309
+        if (isset($dependencies['nextcloud']['@attributes']['max-version'])) {
310
+            $maxVersion = $dependencies['nextcloud']['@attributes']['max-version'];
311
+        } elseif (isset($dependencies['owncloud']['@attributes']['max-version'])) {
312
+            $maxVersion = $dependencies['owncloud']['@attributes']['max-version'];
313
+        } elseif (isset($appInfo['requiremax'])) {
314
+            $maxVersion = $appInfo['requiremax'];
315
+        }
316 316
 
317
-		if (!is_null($minVersion)) {
318
-			if ($this->compareSmaller($this->platform->getOcVersion(), $minVersion)) {
319
-				$missing[] = (string)$this->l->t('Server version %s or higher is required.', [$this->toVisibleVersion($minVersion)]);
320
-			}
321
-		}
322
-		if (!is_null($maxVersion)) {
323
-			if ($this->compareBigger($this->platform->getOcVersion(), $maxVersion)) {
324
-				$missing[] = (string)$this->l->t('Server version %s or lower is required.', [$this->toVisibleVersion($maxVersion)]);
325
-			}
326
-		}
327
-		return $missing;
328
-	}
317
+        if (!is_null($minVersion)) {
318
+            if ($this->compareSmaller($this->platform->getOcVersion(), $minVersion)) {
319
+                $missing[] = (string)$this->l->t('Server version %s or higher is required.', [$this->toVisibleVersion($minVersion)]);
320
+            }
321
+        }
322
+        if (!is_null($maxVersion)) {
323
+            if ($this->compareBigger($this->platform->getOcVersion(), $maxVersion)) {
324
+                $missing[] = (string)$this->l->t('Server version %s or lower is required.', [$this->toVisibleVersion($maxVersion)]);
325
+            }
326
+        }
327
+        return $missing;
328
+    }
329 329
 
330
-	/**
331
-	 * Map the internal version number to the Nextcloud version
332
-	 *
333
-	 * @param string $version
334
-	 * @return string
335
-	 */
336
-	protected function toVisibleVersion($version) {
337
-		switch ($version) {
338
-			case '9.1':
339
-				return '10';
340
-			default:
341
-				if (strpos($version, '9.1.') === 0) {
342
-					$version = '10.0.' . substr($version, 4);
343
-				}
344
-				return $version;
345
-		}
346
-	}
330
+    /**
331
+     * Map the internal version number to the Nextcloud version
332
+     *
333
+     * @param string $version
334
+     * @return string
335
+     */
336
+    protected function toVisibleVersion($version) {
337
+        switch ($version) {
338
+            case '9.1':
339
+                return '10';
340
+            default:
341
+                if (strpos($version, '9.1.') === 0) {
342
+                    $version = '10.0.' . substr($version, 4);
343
+                }
344
+                return $version;
345
+        }
346
+    }
347 347
 
348
-	/**
349
-	 * @param $element
350
-	 * @return mixed
351
-	 */
352
-	private function getValue($element) {
353
-		if (isset($element['@value'])) {
354
-			return $element['@value'];
355
-		}
356
-		return (string)$element;
357
-	}
348
+    /**
349
+     * @param $element
350
+     * @return mixed
351
+     */
352
+    private function getValue($element) {
353
+        if (isset($element['@value'])) {
354
+            return $element['@value'];
355
+        }
356
+        return (string)$element;
357
+    }
358 358
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -140,19 +140,19 @@  discard block
 block discarded – undo
140 140
 		if (isset($dependencies['php']['@attributes']['min-version'])) {
141 141
 			$minVersion = $dependencies['php']['@attributes']['min-version'];
142 142
 			if ($this->compareSmaller($this->platform->getPhpVersion(), $minVersion)) {
143
-				$missing[] = (string)$this->l->t('PHP %s or higher is required.', [$minVersion]);
143
+				$missing[] = (string) $this->l->t('PHP %s or higher is required.', [$minVersion]);
144 144
 			}
145 145
 		}
146 146
 		if (isset($dependencies['php']['@attributes']['max-version'])) {
147 147
 			$maxVersion = $dependencies['php']['@attributes']['max-version'];
148 148
 			if ($this->compareBigger($this->platform->getPhpVersion(), $maxVersion)) {
149
-				$missing[] = (string)$this->l->t('PHP with a version lower than %s is required.', [$maxVersion]);
149
+				$missing[] = (string) $this->l->t('PHP with a version lower than %s is required.', [$maxVersion]);
150 150
 			}
151 151
 		}
152 152
 		if (isset($dependencies['php']['@attributes']['min-int-size'])) {
153 153
 			$intSize = $dependencies['php']['@attributes']['min-int-size'];
154
-			if ($intSize > $this->platform->getIntSize()*8) {
155
-				$missing[] = (string)$this->l->t('%sbit or higher PHP required.', [$intSize]);
154
+			if ($intSize > $this->platform->getIntSize() * 8) {
155
+				$missing[] = (string) $this->l->t('%sbit or higher PHP required.', [$intSize]);
156 156
 			}
157 157
 		}
158 158
 		return $missing;
@@ -175,12 +175,12 @@  discard block
 block discarded – undo
175 175
 		if (!is_array($supportedDatabases)) {
176 176
 			$supportedDatabases = array($supportedDatabases);
177 177
 		}
178
-		$supportedDatabases = array_map(function ($db) {
178
+		$supportedDatabases = array_map(function($db) {
179 179
 			return $this->getValue($db);
180 180
 		}, $supportedDatabases);
181 181
 		$currentDatabase = $this->platform->getDatabase();
182 182
 		if (!in_array($currentDatabase, $supportedDatabases)) {
183
-			$missing[] = (string)$this->l->t('Following databases are supported: %s', [implode(', ', $supportedDatabases)]);
183
+			$missing[] = (string) $this->l->t('Following databases are supported: %s', [implode(', ', $supportedDatabases)]);
184 184
 		}
185 185
 		return $missing;
186 186
 	}
@@ -209,7 +209,7 @@  discard block
 block discarded – undo
209 209
 			}
210 210
 			$commandName = $this->getValue($command);
211 211
 			if (!$this->platform->isCommandKnown($commandName)) {
212
-				$missing[] = (string)$this->l->t('The command line tool %s could not be found', [$commandName]);
212
+				$missing[] = (string) $this->l->t('The command line tool %s could not be found', [$commandName]);
213 213
 			}
214 214
 		}
215 215
 		return $missing;
@@ -275,7 +275,7 @@  discard block
 block discarded – undo
275 275
 			return $missing;
276 276
 		}
277 277
 		if (is_array($oss)) {
278
-			$oss = array_map(function ($os) {
278
+			$oss = array_map(function($os) {
279 279
 				return $this->getValue($os);
280 280
 			}, $oss);
281 281
 		} else {
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
 		}
284 284
 		$currentOS = $this->platform->getOS();
285 285
 		if (!in_array($currentOS, $oss)) {
286
-			$missing[] = (string)$this->l->t('Following platforms are supported: %s', [implode(', ', $oss)]);
286
+			$missing[] = (string) $this->l->t('Following platforms are supported: %s', [implode(', ', $oss)]);
287 287
 		}
288 288
 		return $missing;
289 289
 	}
@@ -316,12 +316,12 @@  discard block
 block discarded – undo
316 316
 
317 317
 		if (!is_null($minVersion)) {
318 318
 			if ($this->compareSmaller($this->platform->getOcVersion(), $minVersion)) {
319
-				$missing[] = (string)$this->l->t('Server version %s or higher is required.', [$this->toVisibleVersion($minVersion)]);
319
+				$missing[] = (string) $this->l->t('Server version %s or higher is required.', [$this->toVisibleVersion($minVersion)]);
320 320
 			}
321 321
 		}
322 322
 		if (!is_null($maxVersion)) {
323 323
 			if ($this->compareBigger($this->platform->getOcVersion(), $maxVersion)) {
324
-				$missing[] = (string)$this->l->t('Server version %s or lower is required.', [$this->toVisibleVersion($maxVersion)]);
324
+				$missing[] = (string) $this->l->t('Server version %s or lower is required.', [$this->toVisibleVersion($maxVersion)]);
325 325
 			}
326 326
 		}
327 327
 		return $missing;
@@ -339,7 +339,7 @@  discard block
 block discarded – undo
339 339
 				return '10';
340 340
 			default:
341 341
 				if (strpos($version, '9.1.') === 0) {
342
-					$version = '10.0.' . substr($version, 4);
342
+					$version = '10.0.'.substr($version, 4);
343 343
 				}
344 344
 				return $version;
345 345
 		}
@@ -353,6 +353,6 @@  discard block
 block discarded – undo
353 353
 		if (isset($element['@value'])) {
354 354
 			return $element['@value'];
355 355
 		}
356
-		return (string)$element;
356
+		return (string) $element;
357 357
 	}
358 358
 }
Please login to merge, or discard this patch.