appName = $AppName; $this->urlGenerator = $urlGenerator; $this->trans = $trans; $this->logger = $logger; $this->config = $config; $this->crypt = $crypt; } /** * Return a unique identifier for the editor * * @return string */ public function getId(): string { return $this->appName; } /** * Return a readable name for the editor * * @return string */ public function getName(): string { return "ONLYOFFICE"; } /** * A list of mimetypes that should open the editor by default * * @return array */ public function getMimetypes(): array { $mimes = array(); if (!$this->config->isUserAllowedToUse()) { return $mimes; } $formats = $this->config->formatsSetting(); foreach ($formats as $format => $setting) { if (array_key_exists("def", $setting) && $setting["def"]) { array_push($mimes, $setting["mime"][0]); } } return $mimes; } /** * A list of mimetypes that can be opened in the editor optionally * * @return array */ public function getMimetypesOptional(): array { $mimes = array(); if (!$this->config->isUserAllowedToUse()) { return $mimes; } $formats = $this->config->formatsSetting(); foreach ($formats as $format => $setting) { if (!array_key_exists("def", $setting) || !$setting["def"]) { array_push($mimes, $setting["mime"][0]); } } return $mimes; } /** * Return a list of file creation options to be presented to the user * * @return array of ACreateFromTemplate|ACreateEmpty */ public function getCreators(): array { if (!$this->config->isUserAllowedToUse()) { return array(); } return [ new FileCreator($this->appName, $this->trans, $this->logger, "docx"), new FileCreator($this->appName, $this->trans, $this->logger, "xlsx"), new FileCreator($this->appName, $this->trans, $this->logger, "pptx") ]; } /** * Return if the view is able to securely view a file without downloading it to the browser * * @return bool */ public function isSecure(): bool { return true; } /** * Return a template response for displaying the editor * * open can only be called once when the client requests the editor with a one-time-use token * For handling editing and later requests, editors need to implement their own token handling * and take care of invalidation * * @param IToken $token - one time token * * @return Response */ public function open(IToken $token): Response { try { $token->useTokenScope(); $file = $token->getFile(); $fileId = $file->getId(); $userId = $token->getUser(); $this->logger->debug("DirectEditor open: $fileId"); if (!$this->config->isUserAllowedToUse($userId)) { return $this->renderError($this->trans->t("Not permitted")); } $documentServerUrl = $this->config->getDocumentServerUrl(); if (empty($documentServerUrl)) { $this->logger->error("documentServerUrl is empty"); return $this->renderError($this->trans->t("ONLYOFFICE app is not configured. Please contact admin")); } $directToken = $this->crypt->getHash([ "userId" => $userId, "fileId" => $fileId, "action" => "direct", "iat" => time(), "exp" => time() + 30 ]); $filePath = $file->getPath(); $filePath = preg_replace("/^\/" . $userId . "\/files/", "", $filePath); $params = [ "fileId" => null, "filePath" => $filePath, "shareToken" => null, "directToken" => $directToken, "isTemplate" => false, "inframe" => false, "inviewer" => false, "anchor" => null ]; $response = new TemplateResponse($this->appName, "editor", $params, "base"); $csp = new ContentSecurityPolicy(); if (preg_match("/^https?:\/\//i", $documentServerUrl)) { $csp->addAllowedScriptDomain($documentServerUrl); $csp->addAllowedFrameDomain($documentServerUrl); } else { $csp->addAllowedFrameDomain("'self'"); } $response->setContentSecurityPolicy($csp); return $response; } catch (\Exception $e) { $this->logger->error($e->getMessage(), ["exception" => $e]); return $this->renderError($e->getMessage()); } } /** * Print error page * * @param string $error - error message * * @return TemplateResponse */ private function renderError($error) { return new TemplateResponse($this->appName, "directeditorerror", [ "error" => $error ], TemplateResponse::RENDER_AS_ERROR); } }