appName; } /** * Return a readable name for the editor */ public function getName(): string { return "ONLYOFFICE"; } /** * A list of mimetypes that should open the editor by default */ public function getMimetypes(): array { $mimes = []; if (!$this->appConfig->isUserAllowedToUse()) { return $mimes; } $formats = $this->appConfig->formatsSetting(); foreach ($formats as $setting) { if (array_key_exists("def", $setting) && $setting["def"]) { $mimes[] = $setting["mime"][0]; } } return $mimes; } /** * A list of mimetypes that can be opened in the editor optionally */ public function getMimetypesOptional(): array { $mimes = []; if (!$this->appConfig->isUserAllowedToUse()) { return $mimes; } $formats = $this->appConfig->formatsSetting(); foreach ($formats as $setting) { if (!array_key_exists("def", $setting) || !$setting["def"]) { $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->appConfig->isUserAllowedToUse()) { return []; } 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 */ 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 */ 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->appConfig->isUserAllowedToUse($userId)) { return $this->renderError($this->trans->t("Not permitted")); } if ($this->appConfig->getRestrictExternalStorage() && $file->getMountPoint() instanceof \OCA\Files_External\Config\ExternalMountPoint) { return $this->renderError($this->trans->t("Opening files with ONLYOFFICE from external storages is restricted. Please contact the admin.")); } $documentServerUrl = $this->appConfig->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/", "", (string) $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 */ private function renderError(string $error): TemplateResponse { return new TemplateResponse($this->appName, "directeditorerror", [ "error" => $error ], TemplateResponse::RENDER_AS_ERROR); } }