$this->share]; $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH)); $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest'); if ($this->share->getSendPasswordByTalk()) { $csp = new ContentSecurityPolicy(); $csp->addAllowedConnectDomain('*'); $csp->addAllowedMediaDomain('blob:'); $response->setContentSecurityPolicy($csp); } return $response; } /** * The template to show when authentication failed */ protected function showAuthFailed(): TemplateResponse { $templateParameters = ['share' => $this->share, 'wrongpw' => true]; $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH)); $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest'); if ($this->share->getSendPasswordByTalk()) { $csp = new ContentSecurityPolicy(); $csp->addAllowedConnectDomain('*'); $csp->addAllowedMediaDomain('blob:'); $response->setContentSecurityPolicy($csp); } return $response; } /** * The template to show after user identification */ protected function showIdentificationResult(bool $success = false): TemplateResponse { $templateParameters = ['share' => $this->share, 'identityOk' => $success]; $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH)); $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest'); if ($this->share->getSendPasswordByTalk()) { $csp = new ContentSecurityPolicy(); $csp->addAllowedConnectDomain('*'); $csp->addAllowedMediaDomain('blob:'); $response->setContentSecurityPolicy($csp); } return $response; } /** * Validate the identity token of a public share * * @param ?string $identityToken * @return bool */ protected function validateIdentity(?string $identityToken = null): bool { if ($this->share->getShareType() !== IShare::TYPE_EMAIL) { return false; } if ($identityToken === null || $this->share->getSharedWith() === null) { return false; } return $identityToken === $this->share->getSharedWith(); } /** * Generates a password for the share, respecting any password policy defined */ protected function generatePassword(): void { $event = new GenerateSecurePasswordEvent(PasswordContext::SHARING); $this->eventDispatcher->dispatchTyped($event); $password = $event->getPassword() ?? $this->secureRandom->generate(20); $this->share->setPassword($password); $this->shareManager->updateShare($this->share); } protected function verifyPassword(string $password): bool { return $this->shareManager->checkPassword($this->share, $password); } protected function getPasswordHash(): ?string { return $this->share->getPassword(); } public function isValidToken(): bool { try { $this->share = $this->shareManager->getShareByToken($this->getToken()); } catch (ShareNotFound $e) { return false; } return true; } protected function isPasswordProtected(): bool { return $this->share->getPassword() !== null; } protected function authSucceeded() { if ($this->share === null) { throw new NotFoundException(); } // For share this was always set so it is still used in other apps $this->session->set(PublicAuth::DAV_AUTHENTICATED, $this->share->getId()); } /** @inheritDoc */ protected function authFailed() { $this->accessService->accessWrongPassword($this->share); } /** * Validate the permissions of the share * * @param Share\IShare $share * @return bool */ private function validateSharePermissions(\OCP\Share\IShare $share) { // If the owner is disabled no access to the link is granted $owner = $this->userManager->get($share->getShareOwner()); if ($owner === null || !$owner->isEnabled()) { return false; } // If the initiator of the share is disabled no access is granted $initiator = $this->userManager->get($share->getSharedBy()); if ($initiator === null || !$initiator->isEnabled()) { return false; } return $share->getNode()->isReadable() && $share->getNode()->isShareable(); } /** * @param string $path * @return TemplateResponse * @throws NotFoundException * @throws \Exception */ #[PublicPage] #[NoCSRFRequired] public function showShare($path = ''): TemplateResponse { \OC_User::setIncognitoMode(true); // Check whether share exists try { $share = $this->shareManager->getShareByToken($this->getToken()); } catch (ShareNotFound $e) { throw new NotFoundException($this->l10n->t('This share does not exist or is no longer available')); } if (!$this->validateSharePermissions($share)) { $this->accessService->shareNotFound($share); throw new NotFoundException($this->l10n->t('This share does not exist or is no longer available')); } $shareNode = $share->getNode(); try { $templateProvider = $this->publicShareTemplateFactory->getProvider($share); $response = $templateProvider->renderPage($share, $this->getToken(), $path); } catch (NotFoundException $e) { $this->accessService->shareNotFound($share); throw new NotFoundException($this->l10n->t('This share does not exist or is no longer available')); } // We can't get the path of a file share if (($shareNode instanceof \OCP\Files\File) && $path !== '') { $this->accessService->shareNotFound($share); throw new NotFoundException($this->l10n->t('This share does not exist or is no longer available')); } $this->accessService->accessShare($share); return $response; } /** * @NoSameSiteCookieRequired * * @param string $token * @param string|null $files * @param string $path * @return void|\OCP\AppFramework\Http\Response * @throws NotFoundException * @deprecated 31.0.0 Users are encouraged to use the DAV endpoint */ #[PublicPage] #[NoCSRFRequired] public function downloadShare($token, $files = null, $path = '') { \OC_User::setIncognitoMode(true); $share = $this->shareManager->getShareByToken($token); if (!$this->validateSharePermissions($share)) { throw new NotFoundException(); } if (!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) { return new \OCP\AppFramework\Http\DataResponse('Share has no read permission', Http::STATUS_FORBIDDEN); } $davUrl = '/public.php/dav/files/' . $token . '/?accept=zip'; if ($files !== null) { $davUrl .= '&files=' . $files; } return new RedirectResponse($this->urlGenerator->getAbsoluteURL($davUrl)); } }