diff --git a/CHANGELOG.md b/CHANGELOG.md index d7c80925..f7b2767f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Change Log +## 4.1.3 +## Added +- inline editor if using the same tab, opening the sidebar, sharing from the editor +- setting zoom and autosave +- selection of a file for comparison (DocumentServer 5.5 required) + +## Changed +- fix file opening if master key encryption is enabled +- fix file opening the federated file when watermark is enabled + ## 4.0.1 ## Added - Polish translation diff --git a/appinfo/app.php b/appinfo/app.php index cbe84af0..1d8b32f0 100644 --- a/appinfo/app.php +++ b/appinfo/app.php @@ -1,7 +1,7 @@ ONLYOFFICE connector enables you to edit Office documents within ONLYOFFICE from the familiar web interface. This will create a new Open in ONLYOFFICE action within the document library for Office documents. This allows multiple users to collaborate in real time and to save back those changes to your file storage. agpl Ascensio System SIA - 4.0.1 + 4.1.3 Onlyoffice diff --git a/appinfo/routes.php b/appinfo/routes.php index dfce8621..9a9a4638 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -1,7 +1,7 @@ userId; \OC_User::setUserId($userId); - $user = $this->userManager->get($userId); - if (!empty($user)) { - \OC_Util::setupFS($userId); + if ($this->config->checkEncryptionModule() === "master") { + \OC_User::setIncognitoMode(true); + } else { + $user = $this->userManager->get($userId); + if (!empty($user)) { + \OC_Util::setupFS($userId); + } } } @@ -399,10 +403,6 @@ public function track($doc, $users, $key, $status, $url, $token) { } } - if ($this->config->checkEncryptionModule() === "master") { - \OC_User::setIncognitoMode(true); - } - // owner of file from the callback link $ownerId = $hashData->ownerId; $owner = $this->userManager->get($ownerId); @@ -422,7 +422,9 @@ public function track($doc, $users, $key, $status, $url, $token) { } } - if (!empty($userId)) { + if ($this->config->checkEncryptionModule() === "master") { + \OC_User::setIncognitoMode(true); + } else if (!empty($userId)) { \OC_Util::setupFS($userId); } diff --git a/controller/editorcontroller.php b/controller/editorcontroller.php index ffe413ed..d70ec3c0 100644 --- a/controller/editorcontroller.php +++ b/controller/editorcontroller.php @@ -1,7 +1,7 @@ logger->error("Can't create file: $name", array("app" => $this->appName)); return ["error" => $this->trans->t("Can't create file")]; + } catch (ForbiddenException $e) { + $this->logger->error("Can't put file: $name", array("app" => $this->appName)); + return ["error" => $this->trans->t("Can't create file")]; } $fileInfo = $file->getFileInfo(); @@ -350,6 +354,9 @@ public function convert($fileId, $shareToken = NULL) { } catch (NotPermittedException $e) { $this->logger->error("Can't create file: $newFileName", array("app" => $this->appName)); return ["error" => $this->trans->t("Can't create file")]; + } catch (ForbiddenException $e) { + $this->logger->error("Can't put file: $newFileName", array("app" => $this->appName)); + return ["error" => $this->trans->t("Can't create file")]; } $fileInfo = $file->getFileInfo(); @@ -410,6 +417,9 @@ public function save($name, $dir, $url) { } catch (NotPermittedException $e) { $this->logger->error("Can't save file: $name", array("app" => $this->appName)); return ["error" => $this->trans->t("Can't create file")]; + } catch (ForbiddenException $e) { + $this->logger->error("Can't put file: $name", array("app" => $this->appName)); + return ["error" => $this->trans->t("Can't create file")]; } $fileInfo = $file->getFileInfo(); @@ -470,15 +480,16 @@ public function url($filePath) { * Print editor section * * @param integer $fileId - file identifier - * @param string $shareToken - access token * @param string $filePath - file path + * @param string $shareToken - access token + * @param bool $inframe - open in frame * * @return TemplateResponse|RedirectResponse * * @NoAdminRequired * @NoCSRFRequired */ - public function index($fileId, $shareToken = NULL, $filePath = NULL) { + public function index($fileId, $filePath = NULL, $shareToken = NULL, $inframe = false) { $this->logger->debug("Open: $fileId $filePath", array("app" => $this->appName)); if (empty($shareToken) && !$this->userSession->isLoggedIn()) { @@ -503,10 +514,16 @@ public function index($fileId, $shareToken = NULL, $filePath = NULL) { "documentServerUrl" => $documentServerUrl, "fileId" => $fileId, "filePath" => $filePath, - "shareToken" => $shareToken + "shareToken" => $shareToken, + "inframe" => false ]; - $response = new TemplateResponse($this->appName, "editor", $params); + if ($inframe === true) { + $params["inframe"] = true; + $response = new TemplateResponse($this->appName, "editor", $params, "plain"); + } else { + $response = new TemplateResponse($this->appName, "editor", $params); + } $csp = new ContentSecurityPolicy(); $csp->allowInlineScript(true); @@ -527,6 +544,7 @@ public function index($fileId, $shareToken = NULL, $filePath = NULL) { * * @param integer $fileId - file identifier * @param string $shareToken - access token + * @param bool $inframe - open in frame * * @return TemplateResponse * @@ -534,8 +552,8 @@ public function index($fileId, $shareToken = NULL, $filePath = NULL) { * @NoCSRFRequired * @PublicPage */ - public function PublicPage($fileId, $shareToken) { - return $this->index($fileId, $shareToken); + public function PublicPage($fileId, $shareToken, $inframe = false) { + return $this->index($fileId, null, $shareToken, $inframe); } /** @@ -544,6 +562,7 @@ public function PublicPage($fileId, $shareToken) { * @param integer $fileId - file identifier * @param string $filePath - file path * @param string $shareToken - access token + * @param integer $inframe - open in frame. 0 - no, 1 - yes, 2 - without goback for old editor (5.4) * @param bool $desktop - desktop label * * @return array @@ -551,7 +570,7 @@ public function PublicPage($fileId, $shareToken) { * @NoAdminRequired * @PublicPage */ - public function config($fileId, $filePath = NULL, $shareToken = NULL, $desktop = false) { + public function config($fileId, $filePath = NULL, $shareToken = NULL, $inframe = 0, $desktop = false) { if (empty($shareToken) && !$this->config->isUserAllowedToUse()) { return ["error" => $this->trans->t("Not permitted")]; @@ -704,7 +723,7 @@ public function config($fileId, $filePath = NULL, $shareToken = NULL, $desktop = } } - if ($folderLink !== NULL) { + if ($folderLink !== NULL && $inframe !== 2) { $params["editorConfig"]["customization"]["goback"] = [ "url" => $folderLink ]; @@ -712,10 +731,17 @@ public function config($fileId, $filePath = NULL, $shareToken = NULL, $desktop = if (!$desktop) { if ($this->config->GetSameTab()) { $params["editorConfig"]["customization"]["goback"]["blank"] = false; + if ($inframe === 1) { + $params["editorConfig"]["customization"]["goback"]["requestClose"] = true; + } } } } + if ($inframe === 1) { + $params["_files_sharing"] = \OC::$server->getAppManager()->isEnabledForUser("files_sharing"); + } + $params = $this->setCustomization($params); if ($this->config->UseDemo()) { @@ -878,6 +904,16 @@ private function setCustomization($params) { $params["editorConfig"]["customization"]["logo"] = $logo; } + $zoom = $this->config->GetSystemValue($this->config->_customization_zoom); + if (isset($zoom)) { + $params["editorConfig"]["customization"]["zoom"] = $zoom; + } + + $autosave = $this->config->GetSystemValue($this->config->_customization_autosave); + if (isset($autosave)) { + $params["editorConfig"]["customization"]["autosave"] = $autosave; + } + return $params; } diff --git a/controller/federationcontroller.php b/controller/federationcontroller.php index 6ce8c434..09cab301 100644 --- a/controller/federationcontroller.php +++ b/controller/federationcontroller.php @@ -1,7 +1,7 @@ config->SelectDemo($demo === true)) { $error = $this->trans->t("The 30-day test period is over, you can no longer connect to demo ONLYOFFICE Document Server."); } diff --git a/css/editor.css b/css/editor.css index 21f52fd9..38b90a5e 100644 --- a/css/editor.css +++ b/css/editor.css @@ -1,6 +1,6 @@ /** * - * (c) Copyright Ascensio System SIA 2019 + * (c) Copyright Ascensio System SIA 2020 * * This program is a free software product. * You can redistribute it and/or modify it under the terms of the GNU Affero General Public License @@ -30,6 +30,9 @@ position: absolute; vertical-align: top; } +#body-public #content { + height: 100%; +} .AscDesktopEditor #header { display: none; diff --git a/css/main.css b/css/main.css index d08922cd..abddaaa8 100644 --- a/css/main.css +++ b/css/main.css @@ -1,6 +1,6 @@ /** * - * (c) Copyright Ascensio System SIA 2019 + * (c) Copyright Ascensio System SIA 2020 * * This program is a free software product. * You can redistribute it and/or modify it under the terms of the GNU Affero General Public License @@ -40,6 +40,54 @@ background-image: url("../img/app-dark.svg"); } +/* onlyoffice-inline */ +body.onlyoffice-inline { + overscroll-behavior-y: none; + overflow: hidden; +} +body.onlyoffice-inline #app-navigation, +body.onlyoffice-inline .searchbox, +body.onlyoffice-inline #app-content #controls { + display: none; +} +body.onlyoffice-inline #content #app-content { + margin-left: 0; +} +#onlyofficeFrame { + background-color: #fff; + width: 100%; + height: calc(100vh - 45px); + display: block; + position: absolute; + top: 0; + z-index: 110; +} + +#onlyofficeHeader { + display: flex; + float: right; +} +.header-right #onlyofficeHeader { + float: left; +} + +#onlyofficeHeader .icon { + display: block; + min-width: 50px; + height: 45px; +} +.header-right #onlyofficeHeader .icon { + height: 31px; +} +#onlyofficeHeader .icon-close { + background-image: url("../img/close.svg"); +} +#onlyofficeHeader .icon-shared { + background-image: url("../img/shared.svg"); + opacity: 1; +} + +/* AscDesktopEditor */ .AscDesktopEditor #header { display: none; } diff --git a/css/settings.css b/css/settings.css index 2d503d8b..160b6aac 100644 --- a/css/settings.css +++ b/css/settings.css @@ -1,6 +1,6 @@ /** * - * (c) Copyright Ascensio System SIA 2019 + * (c) Copyright Ascensio System SIA 2020 * * This program is a free software product. * You can redistribute it and/or modify it under the terms of the GNU Affero General Public License diff --git a/img/close.svg b/img/close.svg new file mode 100644 index 00000000..6e9782e8 --- /dev/null +++ b/img/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/img/shared.svg b/img/shared.svg new file mode 100644 index 00000000..d5edd210 --- /dev/null +++ b/img/shared.svg @@ -0,0 +1,3 @@ + + + diff --git a/js/desktop.js b/js/desktop.js index e8bc18e2..7a00b927 100644 --- a/js/desktop.js +++ b/js/desktop.js @@ -1,6 +1,6 @@ /** * - * (c) Copyright Ascensio System SIA 2019 + * (c) Copyright Ascensio System SIA 2020 * * This program is a free software product. * You can redistribute it and/or modify it under the terms of the GNU Affero General Public License diff --git a/js/editor.js b/js/editor.js index f1687a80..353ea889 100644 --- a/js/editor.js +++ b/js/editor.js @@ -1,6 +1,6 @@ /** * - * (c) Copyright Ascensio System SIA 2019 + * (c) Copyright Ascensio System SIA 2020 * * This program is a free software product. * You can redistribute it and/or modify it under the terms of the GNU Affero General Public License @@ -29,7 +29,8 @@ (function ($, OCA) { OCA.Onlyoffice = _.extend({ - AppName: "onlyoffice" + AppName: "onlyoffice", + inframe: false }, OCA.Onlyoffice); OCA.Onlyoffice.InitEditor = function () { @@ -42,6 +43,7 @@ var fileId = $("#iframeEditor").data("id"); var filePath = $("#iframeEditor").data("path"); var shareToken = $("#iframeEditor").data("sharetoken"); + OCA.Onlyoffice.inframe = !!$("#iframeEditor").data("inframe"); if (!fileId && !shareToken) { displayError(t(OCA.Onlyoffice.AppName, "FileId is empty")); return; @@ -64,6 +66,21 @@ if (shareToken) { params.push("shareToken=" + encodeURIComponent(shareToken)); } + + if (OCA.Onlyoffice.inframe) { + var dsVersion = DocsAPI.DocEditor.version(); + var versionArray = dsVersion.split("."); + if (versionArray[0] < 5 || versionArray[0] == 5 && versionArray[1] < 5) { + window.parent.postMessage({ + method: "editorShowHeaderButton" + }, + "*"); + params.push("inframe=2"); + } else { + params.push("inframe=1"); + } + } + if (OCA.Onlyoffice.Desktop) { params.push("desktop=true"); } @@ -109,10 +126,19 @@ "onDocumentStateChange": setPageTitle, }; - if (OC.currentUser) { + if (OCA.Onlyoffice.inframe && !shareToken + || OC.currentUser) { config.events.onRequestSaveAs = OCA.Onlyoffice.onRequestSaveAs; config.events.onRequestInsertImage = OCA.Onlyoffice.onRequestInsertImage; config.events.onRequestMailMergeRecipients = OCA.Onlyoffice.onRequestMailMergeRecipients; + config.events.onRequestCompareFile = OCA.Onlyoffice.onRequestCompareFile; + } + + if (OCA.Onlyoffice.inframe) { + config.events.onRequestClose = OCA.Onlyoffice.onRequestClose; + if (config._files_sharing && !shareToken) { + config.events.onRequestSharingSettings = OCA.Onlyoffice.onRequestSharingSettings; + } } OCA.Onlyoffice.docEditor = new DocsAPI.DocEditor("iframeEditor", config); @@ -125,57 +151,48 @@ }); }; - OCA.Onlyoffice.onRequestSaveAs = function(event) { - var title = event.data.title; - var url = event.data.url; - - var saveAs = function(fileDir) { - var saveData = { - name: title, - dir: fileDir, - url: url - }; - - $.post(OC.generateUrl("apps/" + OCA.Onlyoffice.AppName + "/ajax/save"), - saveData, - function onSuccess(response) { - if (response.error) { - OC.Notification.show(response.error, { - type: "error", - timeout: 3 - }); - return; - } - - OC.Notification.show(t(OCA.Onlyoffice.AppName, "File saved") + " (" + response.name + ")", { - timeout: 3 - }); - }); + OCA.Onlyoffice.onRequestSaveAs = function (event) { + var saveData = { + name: event.data.title, + url: event.data.url }; - OC.dialogs.filepicker(t(OCA.Onlyoffice.AppName, "Save as"), saveAs, false, "httpd/unix-directory"); + if (OCA.Onlyoffice.inframe) { + window.parent.postMessage({ + method: "editorRequestSaveAs", + param: saveData + }, + "*"); + } else { + OC.dialogs.filepicker(t(OCA.Onlyoffice.AppName, "Save as"), + function (fileDir) { + saveData.dir = fileDir; + OCA.Onlyoffice.editorSaveAs(saveData); + }, + false, + "httpd/unix-directory"); + } }; - OCA.Onlyoffice.onRequestInsertImage = function() { - - var insertImage = function(filePath) { - $.get(OC.generateUrl("apps/" + OCA.Onlyoffice.AppName + "/ajax/url?filePath={filePath}", - { - filePath: filePath - }), - function onSuccess(response) { - if (response.error) { - OC.Notification.show(response.error, { - type: "error", - timeout: 3 - }); - return; - } + OCA.Onlyoffice.editorSaveAs = function (saveData) { + $.post(OC.generateUrl("apps/" + OCA.Onlyoffice.AppName + "/ajax/save"), + saveData, + function onSuccess(response) { + if (response.error) { + OC.Notification.show(response.error, { + type: "error", + timeout: 3 + }); + return; + } - OCA.Onlyoffice.docEditor.insertImage(response); + OC.Notification.show(t(OCA.Onlyoffice.AppName, "File saved") + " (" + response.name + ")", { + timeout: 3 }); - }; + }); + }; + OCA.Onlyoffice.onRequestInsertImage = function () { var imageMimes = [ "image/bmp", "image/x-bmp", "image/x-bitmap", "application/bmp", "image/gif", @@ -183,34 +200,115 @@ "image/png", "image/x-png", "application/png", "application/x-png" ]; - OC.dialogs.filepicker(t(OCA.Onlyoffice.AppName, "Insert image"), insertImage, false, imageMimes); + if (OCA.Onlyoffice.inframe) { + window.parent.postMessage({ + method: "editorRequestInsertImage", + param: imageMimes + }, + "*"); + } else { + OC.dialogs.filepicker(t(OCA.Onlyoffice.AppName, "Insert image"), OCA.Onlyoffice.editorInsertImage, false, imageMimes); + } }; - OCA.Onlyoffice.onRequestMailMergeRecipients = function() { - - var setRecipient = function(filePath) { - $.get(OC.generateUrl("apps/" + OCA.Onlyoffice.AppName + "/ajax/url?filePath={filePath}", - { - filePath: filePath - }), - function onSuccess(response) { - if (response.error) { - OC.Notification.show(response.error, { - type: "error", - timeout: 3 - }); - return; - } + OCA.Onlyoffice.editorInsertImage = function (filePath) { + $.get(OC.generateUrl("apps/" + OCA.Onlyoffice.AppName + "/ajax/url?filePath={filePath}", + { + filePath: filePath + }), + function onSuccess(response) { + if (response.error) { + OC.Notification.show(response.error, { + type: "error", + timeout: 3 + }); + return; + } - OCA.Onlyoffice.docEditor.setMailMergeRecipients(response); - }); - }; + OCA.Onlyoffice.docEditor.insertImage(response); + }); + }; + OCA.Onlyoffice.onRequestMailMergeRecipients = function () { var recipientMimes = [ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ]; - OC.dialogs.filepicker(t(OCA.Onlyoffice.AppName, "Select recipients"), setRecipient, false, recipientMimes); + if (OCA.Onlyoffice.inframe) { + window.parent.postMessage({ + method: "editorRequestMailMergeRecipients", + param: recipientMimes + }, + "*"); + } else { + OC.dialogs.filepicker(t(OCA.Onlyoffice.AppName, "Select recipients"), OCA.Onlyoffice.editorSetRecipient, false, recipientMimes); + } + }; + + OCA.Onlyoffice.editorSetRecipient = function (filePath) { + $.get(OC.generateUrl("apps/" + OCA.Onlyoffice.AppName + "/ajax/url?filePath={filePath}", + { + filePath: filePath + }), + function onSuccess(response) { + if (response.error) { + OC.Notification.show(response.error, { + type: "error", + timeout: 3 + }); + return; + } + + OCA.Onlyoffice.docEditor.setMailMergeRecipients(response); + }); + }; + + OCA.Onlyoffice.onRequestClose = function () { + window.parent.postMessage({ + method: "editorRequestClose" + }, + "*"); + }; + + OCA.Onlyoffice.onRequestSharingSettings = function() { + window.parent.postMessage({ + method: "editorRequestSharingSettings" + }, + "*"); + }; + + OCA.Onlyoffice.onRequestCompareFile = function() { + var revisedMimes = [ + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" + ]; + + if (OCA.Onlyoffice.inframe) { + window.parent.postMessage({ + method: "editorRequestCompareFile", + param: revisedMimes + }, + "*"); + } else { + OC.dialogs.filepicker(t(OCA.Onlyoffice.AppName, "Select file to compare"), OCA.Onlyoffice.editorSetRevised, false, revisedMimes); + } + }; + + OCA.Onlyoffice.editorSetRevised = function(filePath) { + $.get(OC.generateUrl("apps/" + OCA.Onlyoffice.AppName + "/ajax/url?filePath={filePath}", + { + filePath: filePath + }), + function onSuccess(response) { + if (response.error) { + OC.Notification.show(response.error, { + type: "error", + timeout: 3 + }); + return; + } + + OCA.Onlyoffice.docEditor.setRevisedFile(response); + }); }; $(document).ready(OCA.Onlyoffice.InitEditor); diff --git a/js/main.js b/js/main.js index 0d11f575..056d2f61 100644 --- a/js/main.js +++ b/js/main.js @@ -1,6 +1,6 @@ /** * - * (c) Copyright Ascensio System SIA 2019 + * (c) Copyright Ascensio System SIA 2020 * * This program is a free software product. * You can redistribute it and/or modify it under the terms of the GNU Affero General Public License @@ -29,7 +29,9 @@ (function (OCA) { OCA.Onlyoffice = _.extend({ - AppName: "onlyoffice" + AppName: "onlyoffice", + context: null, + folderUrl: null }, OCA.Onlyoffice); OCA.Onlyoffice.setting = {}; @@ -71,6 +73,9 @@ fileList.add(response, { animate: true }); OCA.Onlyoffice.OpenEditor(response.id, dir, response.name, winEditor); + OCA.Onlyoffice.context = { fileList: fileList }; + OCA.Onlyoffice.context.fileName = response.name; + OC.Notification.show(t(OCA.Onlyoffice.AppName, "File created"), { timeout: 3 }); @@ -98,14 +103,82 @@ winEditor.location.href = url; } else if (!OCA.Onlyoffice.setting.sameTab || OCA.Onlyoffice.Desktop) { winEditor = window.open(url, "_blank"); - } else { + } else if ($("#isPublic").val() === "1" && !$("#filestable").length) { location.href = url; + } else { + var $iframe = $("