urlGenerator = $urlGenerator; $this->rootFolder = $rootFolder; $this->shareManager = $shareManager; $this->userId = $UserId; $this->bookmarkService = $bookmarkService; $this->preferenceService = $preferenceService; } /** * @PublicPage * @NoCSRFRequired */ public function showReader(): TemplateResponse { $templates = [ 'application/epub+zip' => 'epubreader', 'application/x-cbr' => 'cbreader', 'application/pdf' => 'pdfreader', ]; $fileInfo = $this->getFileInfo((string) $this->request->getParam('file')); /** @var int $fileId */ $fileId = $fileInfo['fileId']; $type = (string) $this->request->getParam('type'); $scope = $template = $templates[$type]; $params = [ 'urlGenerator' => $this->urlGenerator, 'downloadLink' => $this->request->getParam('file'), 'scope' => $scope, 'fileId' => $fileInfo['fileId'], 'fileName' => $fileInfo['fileName'], 'fileType' => $fileInfo['fileType'], 'cursor' => $this->toJson($this->bookmarkService->getCursor($fileId)), 'defaults' => $this->toJson($this->preferenceService->getDefault($scope)), 'preferences' => $this->toJson($this->preferenceService->get($scope, $fileId)), 'metadata' => $this->toJson([]), 'annotations' => $this->toJson($this->bookmarkService->get($fileId)), ]; $policy = new ContentSecurityPolicy(); $policy->addAllowedStyleDomain('\'self\''); $policy->addAllowedStyleDomain('blob:'); $policy->addAllowedScriptDomain('\'self\''); $policy->addAllowedFrameDomain('\'self\''); $policy->addAllowedFontDomain('\'self\''); $policy->addAllowedFontDomain('data:'); $policy->addAllowedFontDomain('blob:'); $policy->addAllowedImageDomain('blob:'); $response = new TemplateResponse($this->appName, $template, $params, 'blank'); $response->setContentSecurityPolicy($policy); return $response; } /** * @brief sharing-aware file info retriever * * Work around the differences between normal and shared file access * (this should be abstracted away in OC/NC IMnsHO) * * @param string $path path-fragment from url * * @throws InvalidPathException|NotFoundException */ private function getFileInfo(string $path): array { $count = 0; $shareToken = preg_replace('/(?:\\/index\\.php)?\\/s\\/([A-Za-z0-9]{15,32})\\/download.*/', '$1', $path, 1, $count); if (1 === $count) { /* shared file or directory */ $node = $this->shareManager->getShareByToken($shareToken)->getNode(); $type = $node->getType(); /* shared directory, need file path to continue, */ if (FileInfo::TYPE_FOLDER == $type && $node instanceof Folder) { $query = []; parse_str(parse_url($path, PHP_URL_QUERY), $query); if (isset($query['path']) && is_string($query['path'])) { $node = $node->get($query['path']); } elseif (isset($query['files']) && is_string($query['files'])) { $node = $node->get($query['files']); } else { throw new NotFoundException('Shared file path or name not set'); } } $filePath = $node->getPath(); $fileId = $node->getId(); } else { $filePath = $path; $fileId = $this->rootFolder->getUserFolder($this->userId) ->get(preg_replace('/.*\\/remote.php\\/webdav(.*)/', '$1', rawurldecode((string) $this->request->getParam('file')))) ->getId() ; } $pathInfo = pathinfo($filePath); return [ 'fileName' => $pathInfo['filename'], 'fileType' => strtolower($pathInfo['extension'] ?? ''), 'fileId' => $fileId, ]; } private function toJson(array $value): string { return htmlspecialchars(json_encode($value), ENT_QUOTES, 'UTF-8'); } }