Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ONLYOFFICE/onlyoffice-nextcloud.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Linnik <sergey.linnik@onlyoffice.com>2020-01-16 14:19:44 +0300
committerGitHub <noreply@github.com>2020-01-16 14:19:44 +0300
commitc05cbbf9a226810fa24b8e02371c7f9aee504072 (patch)
tree290092a0ed6946e44bab8eb9a1eca5f82adf0c9f
parente36552830c0559ef689ec9e61267c5079961f7df (diff)
parent3f3a533563f70a8f89cc04e7c7a6f8acc9a4d50f (diff)
Merge pull request #209 from ONLYOFFICE/developv4.1.0
Release/4.1.0
-rw-r--r--CHANGELOG.md11
-rw-r--r--appinfo/application.php32
-rw-r--r--appinfo/info.xml4
-rw-r--r--controller/callbackcontroller.php8
-rw-r--r--controller/editorcontroller.php120
-rw-r--r--controller/federationcontroller.php2
-rw-r--r--css/editor.css5
-rw-r--r--css/main.css34
-rw-r--r--js/directeditor.js76
-rw-r--r--js/editor.js244
-rw-r--r--js/main.js133
-rw-r--r--l10n/de.js3
-rw-r--r--l10n/de.json3
-rw-r--r--l10n/de_DE.js3
-rw-r--r--l10n/de_DE.json3
-rw-r--r--l10n/es.js3
-rw-r--r--l10n/es.json3
-rw-r--r--l10n/fr.js3
-rw-r--r--l10n/fr.json3
-rw-r--r--l10n/pt_BR.js3
-rw-r--r--l10n/pt_BR.json3
-rw-r--r--l10n/ru.js3
-rw-r--r--l10n/ru.json3
-rw-r--r--lib/appconfig.php14
-rw-r--r--lib/directeditor.php275
-rw-r--r--lib/filecreator.php194
-rw-r--r--templates/editor.php10
27 files changed, 1063 insertions, 135 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 26bc87b..108c355 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,16 @@
# Change Log
+## 4.1.0
+## Added
+- inline editor if using the same tab, opening the sidebar, sharing from the editor
+- creating, editing and co-authoring files in Nextcloud Android mobile application
+- setting zoom and autosave
+- selection of a file for comparison (DocumentServer 5.5 required)
+
+## Changed
+- compatible with Nextcloud 18
+- Nextcloud v15 is no longer supported
+
## 4.0.0
## Added
- Polish translation
diff --git a/appinfo/application.php b/appinfo/application.php
index 4aac65e..8b178c6 100644
--- a/appinfo/application.php
+++ b/appinfo/application.php
@@ -30,6 +30,7 @@
namespace OCA\Onlyoffice\AppInfo;
use OCP\AppFramework\App;
+use OCP\DirectEditing\RegisterDirectEditorEvent;
use OCP\Share\IManager;
use OCP\Util;
@@ -38,6 +39,7 @@ use OCA\Onlyoffice\Controller\CallbackController;
use OCA\Onlyoffice\Controller\EditorController;
use OCA\Onlyoffice\Controller\SettingsController;
use OCA\Onlyoffice\Crypt;
+use OCA\Onlyoffice\DirectEditor;
class Application extends App {
@@ -103,6 +105,10 @@ class Application extends App {
return $c->query("ServerContainer")->getUserSession();
});
+ $container->registerService("UserManager", function($c) {
+ return $c->query("ServerContainer")->getUserManager();
+ });
+
$container->registerService("Logger", function($c) {
return $c->query("ServerContainer")->getLogger();
});
@@ -111,6 +117,27 @@ class Application extends App {
return $c->query("ServerContainer")->getURLGenerator();
});
+ if (class_exists("OCP\DirectEditing\RegisterDirectEditorEvent")) {
+ $container->registerService("DirectEditor", function($c) {
+ return new DirectEditor(
+ $c->query("AppName"),
+ $c->query("URLGenerator"),
+ $c->query("L10N"),
+ $c->query("Logger"),
+ $this->appConfig,
+ $this->crypt
+ );
+ });
+
+ $eventDispatcher->addListener(RegisterDirectEditorEvent::class,
+ function (RegisterDirectEditorEvent $event) use ($container) {
+ if (!empty($this->appConfig->GetDocumentServerUrl()) && $this->appConfig->SettingsAreSuccessful()) {
+ $editor = $container->query("DirectEditor");
+ $event->register($editor);
+ }
+ });
+ }
+
// Controllers
$container->registerService("SettingsController", function($c) {
@@ -131,6 +158,7 @@ class Application extends App {
$c->query("Request"),
$c->query("RootStorage"),
$c->query("UserSession"),
+ $c->query("UserManager"),
$c->query("URLGenerator"),
$c->query("L10N"),
$c->query("Logger"),
@@ -148,7 +176,7 @@ class Application extends App {
$c->query("Request"),
$c->query("RootStorage"),
$c->query("UserSession"),
- $c->query("ServerContainer")->getUserManager(),
+ $c->query("UserManager"),
$c->query("L10N"),
$c->query("Logger"),
$this->appConfig,
@@ -157,4 +185,4 @@ class Application extends App {
);
});
}
-} \ No newline at end of file
+}
diff --git a/appinfo/info.xml b/appinfo/info.xml
index 78987c6..3644de2 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -6,7 +6,7 @@
<description>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.</description>
<licence>agpl</licence>
<author mail="dev@onlyoffice.com" homepage="https://www.onlyoffice.com/">Ascensio System SIA</author>
- <version>4.0.0</version>
+ <version>4.1.0</version>
<namespace>Onlyoffice</namespace>
<types>
<filesystem/>
@@ -29,7 +29,7 @@
<screenshot>https://raw.githubusercontent.com/ONLYOFFICE/onlyoffice-nextcloud/master/screenshots/new.png</screenshot>
<screenshot>https://raw.githubusercontent.com/ONLYOFFICE/onlyoffice-nextcloud/master/screenshots/open.png</screenshot>
<dependencies>
- <nextcloud min-version="15" max-version="17"/>
+ <nextcloud min-version="16" max-version="18"/>
</dependencies>
<settings>
<admin>OCA\Onlyoffice\AdminSettings</admin>
diff --git a/controller/callbackcontroller.php b/controller/callbackcontroller.php
index 2245086..4034752 100644
--- a/controller/callbackcontroller.php
+++ b/controller/callbackcontroller.php
@@ -132,7 +132,7 @@ class CallbackController extends Controller {
* @param string $AppName - application name
* @param IRequest $request - request object
* @param IRootFolder $root - root folder
- * @param IUserSession $userSession - user session
+ * @param IUserSession $userSession - current user session
* @param IUserManager $userManager - user manager
* @param IL10N $trans - l10n service
* @param ILogger $logger - logger
@@ -140,7 +140,7 @@ class CallbackController extends Controller {
* @param OCA\Onlyoffice\Crypt $crypt - hash generator
* @param IManager $shareManager - Share manager
*/
- public function __construct($AppName,
+ public function __construct($AppName,
IRequest $request,
IRootFolder $root,
IUserSession $userSession,
@@ -415,7 +415,7 @@ class CallbackController extends Controller {
list ($file, $error) = empty($shareToken) ? $this->getFile($userId, $fileId, $filePath) : $this->getFileByToken($fileId, $shareToken);
if (isset($error)) {
- $this->logger->error("track error $fileId" . " " . json_encode($error->getData()), array("app" => $this->appName));
+ $this->logger->error("track error $fileId " . json_encode($error->getData()), array("app" => $this->appName));
return $error;
}
@@ -611,4 +611,4 @@ class CallbackController extends Controller {
usleep(500000);
}
}
-} \ No newline at end of file
+}
diff --git a/controller/editorcontroller.php b/controller/editorcontroller.php
index 1207c23..112e947 100644
--- a/controller/editorcontroller.php
+++ b/controller/editorcontroller.php
@@ -45,6 +45,7 @@ use OCP\ILogger;
use OCP\IRequest;
use OCP\ISession;
use OCP\IURLGenerator;
+use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
@@ -56,6 +57,7 @@ use OCA\Files\Helper;
use OCA\Onlyoffice\AppConfig;
use OCA\Onlyoffice\Crypt;
use OCA\Onlyoffice\DocumentService;
+use OCA\Onlyoffice\FileCreator;
use OCA\Onlyoffice\FileUtility;
/**
@@ -71,6 +73,13 @@ class EditorController extends Controller {
private $userSession;
/**
+ * User manager
+ *
+ * @var IUserManager
+ */
+ private $userManager;
+
+ /**
* Root folder
*
* @var IRootFolder
@@ -129,6 +138,7 @@ class EditorController extends Controller {
* @param IRequest $request - request object
* @param IRootFolder $root - root folder
* @param IUserSession $userSession - current user session
+ * @param IUserManager $userManager - user manager
* @param IURLGenerator $urlGenerator - url generator service
* @param IL10N $trans - l10n service
* @param ILogger $logger - logger
@@ -141,6 +151,7 @@ class EditorController extends Controller {
IRequest $request,
IRootFolder $root,
IUserSession $userSession,
+ IUserManager $userManager,
IURLGenerator $urlGenerator,
IL10N $trans,
ILogger $logger,
@@ -152,6 +163,7 @@ class EditorController extends Controller {
parent::__construct($AppName, $request);
$this->userSession = $userSession;
+ $this->userManager = $userManager;
$this->root = $root;
$this->urlGenerator = $urlGenerator;
$this->trans = $trans;
@@ -213,17 +225,7 @@ class EditorController extends Controller {
return ["error" => $this->trans->t("You don't have enough permission to create")];
}
- $ext = strtolower("." . pathinfo($name, PATHINFO_EXTENSION));
-
- $lang = \OC::$server->getL10NFactory("")->get("")->getLanguageCode();
-
- $templatePath = $this->getTemplatePath($lang, $ext);
- if (!file_exists($templatePath)) {
- $lang = "en";
- $templatePath = $this->getTemplatePath($lang, $ext);
- }
-
- $template = file_get_contents($templatePath);
+ $template = FileCreator::GetTemplate($name);
if (!$template) {
$this->logger->error("Template for file creation not found: $templatePath", array("app" => $this->appName));
return ["error" => $this->trans->t("Template not found")];
@@ -247,18 +249,6 @@ class EditorController extends Controller {
}
/**
- * Get template path
- *
- * @param string $lang - language
- * @param string $ext - file extension
- *
- * @return string
- */
- private function getTemplatePath($lang, $ext) {
- return dirname(__DIR__) . DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR . $lang . DIRECTORY_SEPARATOR . "new" . $ext;
- }
-
- /**
* Conversion file to Office Open XML format
*
* @param integer $fileId - file identifier
@@ -469,15 +459,16 @@ class EditorController extends Controller {
* 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()) {
@@ -502,10 +493,17 @@ class EditorController extends Controller {
"documentServerUrl" => $documentServerUrl,
"fileId" => $fileId,
"filePath" => $filePath,
- "shareToken" => $shareToken
+ "shareToken" => $shareToken,
+ "directToken" => null,
+ "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);
@@ -526,6 +524,7 @@ class EditorController extends Controller {
*
* @param integer $fileId - file identifier
* @param string $shareToken - access token
+ * @param bool $inframe - open in frame
*
* @return TemplateResponse
*
@@ -533,8 +532,8 @@ class EditorController extends Controller {
* @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);
}
/**
@@ -543,6 +542,8 @@ class EditorController extends Controller {
* @param integer $fileId - file identifier
* @param string $filePath - file path
* @param string $shareToken - access token
+ * @param string $directToken - direct 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
@@ -550,16 +551,32 @@ class EditorController extends Controller {
* @NoAdminRequired
* @PublicPage
*/
- public function config($fileId, $filePath = NULL, $shareToken = NULL, $desktop = false) {
+ public function config($fileId, $filePath = NULL, $shareToken = NULL, $directToken = null, $inframe = 0, $desktop = false) {
if (empty($shareToken) && !$this->config->isUserAllowedToUse()) {
- return ["error" => $this->trans->t("Not permitted")];
- }
+ if (empty($directToken)) {
+ return ["error" => $this->trans->t("Not permitted")];
+ } else {
+ list ($directData, $error) = $this->crypt->ReadHash($directToken);
+ if ($directData === NULL) {
+ $this->logger->error("Config for directEditor with empty or not correct hash: $error", array("app" => $this->appName));
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+ if ($directData->action !== "direct") {
+ $this->logger->error("Config for directEditor with other data", array("app" => $this->appName));
+ return ["error" => $this->trans->t("Invalid request")];
+ }
- $user = $this->userSession->getUser();
- $userId = NULL;
- if (!empty($user)) {
- $userId = $user->getUID();
+ $fileId = $directData->fileId;
+ $userId = $directData->userId;
+ $user = $this->userManager->get($userId);
+ }
+ } else {
+ $user = $this->userSession->getUser();
+ $userId = NULL;
+ if (!empty($user)) {
+ $userId = $user->getUID();
+ }
}
list ($file, $error, $share) = empty($shareToken) ? $this->getFile($userId, $fileId, $filePath) : $this->fileUtility->getFileByToken($fileId, $shareToken);
@@ -662,7 +679,7 @@ class EditorController extends Controller {
}
}
- if ($folderLink !== NULL) {
+ if ($folderLink !== NULL && $inframe !== 2) {
$params["editorConfig"]["customization"]["goback"] = [
"url" => $folderLink
];
@@ -670,10 +687,17 @@ class EditorController extends Controller {
if (!$desktop) {
if ($this->config->GetSameTab()) {
$params["editorConfig"]["customization"]["goback"]["blank"] = false;
+ if ($inframe === 1 || !empty($directToken)) {
+ $params["editorConfig"]["customization"]["goback"]["requestClose"] = true;
+ }
}
}
}
+ if ($inframe === 1) {
+ $params["_files_sharing"] = \OC::$server->getAppManager()->isInstalled("files_sharing");
+ }
+
$params = $this->setCustomization($params);
$params = $this->setWatermark($params, !empty($shareToken), $userId, $file);
@@ -837,6 +861,16 @@ class EditorController extends Controller {
$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;
}
@@ -965,10 +999,12 @@ class EditorController extends Controller {
*/
private function renderError($error, $hint = "") {
return new TemplateResponse("", "error", array(
- "errors" => array(array(
- "error" => $error,
- "hint" => $hint
- ))
+ "errors" => array(
+ array(
+ "error" => $error,
+ "hint" => $hint
+ )
+ )
), "error");
}
-} \ No newline at end of file
+}
diff --git a/controller/federationcontroller.php b/controller/federationcontroller.php
index 1be87c7..a3117cb 100644
--- a/controller/federationcontroller.php
+++ b/controller/federationcontroller.php
@@ -123,4 +123,4 @@ class FederationController extends OCSController {
return new DataResponse(["key" => $key]);
}
-} \ No newline at end of file
+}
diff --git a/css/editor.css b/css/editor.css
index 7cfebd3..01dc090 100644
--- a/css/editor.css
+++ b/css/editor.css
@@ -29,6 +29,11 @@
#content.app-onlyoffice {
min-height: calc(100% - 50px);
}
+
+#body-public #content {
+ height: 100%;
+}
+
#app > iframe {
position: absolute;
vertical-align: top;
diff --git a/css/main.css b/css/main.css
index 513c9a8..2dbc794 100644
--- a/css/main.css
+++ b/css/main.css
@@ -40,6 +40,40 @@
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 - 50px);
+ display: block;
+ position: absolute;
+ top: 0;
+ z-index: 110;
+}
+
+#onlyofficeHeader {
+ display: flex;
+}
+
+#onlyofficeHeader .icon {
+ display: block;
+ min-width: 50px;
+ height: 50px;
+}
+
+/* AscDesktopEditor */
.AscDesktopEditor #body-user #header {
display: none;
}
diff --git a/js/directeditor.js b/js/directeditor.js
new file mode 100644
index 0000000..e29dabd
--- /dev/null
+++ b/js/directeditor.js
@@ -0,0 +1,76 @@
+/**
+ *
+ * (c) Copyright Ascensio System SIA 2019
+ *
+ * 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
+ * (AGPL) version 3 as published by the Free Software Foundation.
+ * In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
+ * that Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
+ *
+ * This program is distributed WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * For details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
+ *
+ * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha street, Riga, Latvia, EU, LV-1050.
+ *
+ * The interactive user interfaces in modified source and object code versions of the Program
+ * must display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
+ *
+ * Pursuant to Section 7(b) of the License you must retain the original Product logo when distributing the program.
+ * Pursuant to Section 7(e) we decline to grant you any rights under trademark law for use of our trademarks.
+ *
+ * All the Product's GUI elements, including illustrations and icon sets, as well as technical
+ * writing content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International.
+ * See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
+ *
+ */
+
+(function (OCA) {
+
+ OCA.Onlyoffice = _.extend({}, OCA.Onlyoffice);
+
+ var callMobileMessage = function (messageName, attributes) {
+ var message = messageName
+ if (typeof attributes !== "undefined") {
+ message = {
+ MessageName: messageName,
+ Values: attributes,
+ };
+ }
+ var attributesString = null
+ try {
+ attributesString = JSON.stringify(attributes);
+ } catch (e) {
+ attributesString = null;
+ }
+
+ // Forward to mobile handler
+ if (window.DirectEditingMobileInterface && typeof window.DirectEditingMobileInterface[messageName] === "function") {
+ if (attributesString === null || typeof attributesString === "undefined") {
+ window.DirectEditingMobileInterface[messageName]();
+ } else {
+ window.DirectEditingMobileInterface[messageName](attributesString);
+ }
+ }
+
+ // iOS webkit fallback
+ if (window.webkit
+ && window.webkit.messageHandlers
+ && window.webkit.messageHandlers.DirectEditingMobileInterface) {
+ window.webkit.messageHandlers.DirectEditingMobileInterface.postMessage(message);
+ }
+
+ window.postMessage(message);
+ }
+
+ OCA.Onlyoffice.directEditor = {
+ close: function() {
+ callMobileMessage("close");
+ },
+ loaded: function() {
+ callMobileMessage("loaded");
+ }
+ };
+
+})(OCA);
diff --git a/js/editor.js b/js/editor.js
index 64ffef3..ab9682a 100644
--- a/js/editor.js
+++ b/js/editor.js
@@ -29,7 +29,8 @@
(function ($, OCA) {
OCA.Onlyoffice = _.extend({
- AppName: "onlyoffice"
+ AppName: "onlyoffice",
+ inframe: false
}, OCA.Onlyoffice);
OCA.Onlyoffice.InitEditor = function () {
@@ -40,9 +41,10 @@
};
var fileId = $("#iframeEditor").data("id");
- var filePath = $("#iframeEditor").data("path");
var shareToken = $("#iframeEditor").data("sharetoken");
- if (!fileId && !shareToken) {
+ var directToken = $("#iframeEditor").data("directtoken");
+ OCA.Onlyoffice.inframe = !!$("#iframeEditor").data("inframe");
+ if (!fileId && !shareToken && !directToken) {
displayError(t(OCA.Onlyoffice.AppName, "FileId is empty"));
return;
}
@@ -58,12 +60,31 @@
});
var params = [];
+ var filePath = $("#iframeEditor").data("path");
if (filePath) {
params.push("filePath=" + encodeURIComponent(filePath));
}
if (shareToken) {
params.push("shareToken=" + encodeURIComponent(shareToken));
}
+ if (directToken) {
+ $("html").addClass("onlyoffice-full-page");
+ params.push("directToken=" + encodeURIComponent(directToken));
+ }
+
+ var dsVersion = DocsAPI.DocEditor.version();
+ var versionArray = dsVersion.split(".");
+ if (versionArray[0] < 5 || versionArray[1] < 5) {
+ if (OCA.Onlyoffice.inframe) {
+ window.parent.postMessage({
+ method: "editorShowHeaderButton"
+ });
+ }
+ params.push("inframe=2");
+ } else if (OCA.Onlyoffice.inframe) {
+ params.push("inframe=1");
+ }
+
if (OCA.Onlyoffice.Desktop) {
params.push("desktop=true");
}
@@ -109,15 +130,29 @@
"onDocumentStateChange": setPageTitle,
};
- if (OC.currentUser) {
+ if (OCA.Onlyoffice.inframe || 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.directEditor || OCA.Onlyoffice.inframe) {
+ config.events.onRequestClose = OCA.Onlyoffice.onRequestClose;
+ }
+
+ if (OCA.Onlyoffice.inframe && config._files_sharing && !shareToken) {
+ config.events.onRequestSharingSettings = OCA.Onlyoffice.onRequestSharingSettings;
}
OCA.Onlyoffice.docEditor = new DocsAPI.DocEditor("iframeEditor", config);
- if (config.type === "mobile" && $("#app > iframe").css("position") === "fixed") {
+ if (OCA.Onlyoffice.directEditor) {
+ OCA.Onlyoffice.directEditor.loaded();
+ }
+
+ if (!OCA.Onlyoffice.directEditor
+ && config.type === "mobile" && $("#app > iframe").css("position") === "fixed") {
$("#app > iframe").css("height", "calc(100% - 50px)");
}
}
@@ -125,57 +160,47 @@
});
};
- 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 +208,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 () {
+ if (OCA.Onlyoffice.directEditor) {
+ OCA.Onlyoffice.directEditor.close();
+ return;
+ }
+
+ 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 5bd4d3e..5b388f5 100644
--- a/js/main.js
+++ b/js/main.js
@@ -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,77 @@
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 = $("<iframe id=\"onlyofficeFrame\" nonce=\"" + btoa(OC.requestToken) + "\" scrolling=\"no\" allowfullscreen src=\"" + url + "&inframe=true\" />");
+ $("#app-content").append($iframe);
+
+ $("body").addClass("onlyoffice-inline");
+ OC.Apps.hideAppSidebar();
+
+ $("html, body").scrollTop(0);
+
+ OCA.Onlyoffice.folderUrl = location.href;
+ window.history.pushState(null, null, url);
+ }
+ };
+
+ OCA.Onlyoffice.ShowHeaderButton = function () {
+ var wrapper = $("<div id='onlyofficeHeader' />")
+
+ var btnClose = $("<a class='icon icon-close-white'></a>");
+ btnClose.on("click", function() {
+ OCA.Onlyoffice.CloseEditor();
+ });
+ wrapper.prepend(btnClose);
+
+ if (!$("#isPublic").val()) {
+ var btnShare = $("<a class='icon icon-shared icon-white'></a>");
+ btnShare.on("click", function () {
+ OCA.Onlyoffice.OpenShareDialog();
+ })
+ wrapper.prepend(btnShare);
+ }
+
+ if (!$("#header .header-right").length) {
+ $("#header").append("<div class='header-right'></div>");
+ }
+ wrapper.prependTo(".header-right");
+ };
+
+ OCA.Onlyoffice.CloseEditor = function () {
+ $("body").removeClass("onlyoffice-inline");
+
+ $("#onlyofficeFrame").remove();
+ $("#onlyofficeHeader").remove();
+
+ OCA.Onlyoffice.context = null;
+
+ var url = OCA.Onlyoffice.folderUrl;
+ if (!!url) {
+ window.history.pushState(null, null, url);
+ OCA.Onlyoffice.folderUrl = null;
+ }
+ };
+
+ OCA.Onlyoffice.OpenShareDialog = function () {
+ if (OCA.Onlyoffice.context) {
+ if (!$("#app-sidebar").is(":visible")) {
+ OCA.Onlyoffice.context.fileList.showDetailsView(OCA.Onlyoffice.context.fileName, "shareTabView");
+ OC.Apps.showAppSidebar();
+ } else {
+ OC.Apps.hideAppSidebar();
+ }
}
};
OCA.Onlyoffice.FileClick = function (fileName, context) {
var fileInfoModel = context.fileInfoModel || context.fileList.getModelForFile(fileName);
OCA.Onlyoffice.OpenEditor(fileInfoModel.id, context.dir, fileName);
+
+ OCA.Onlyoffice.context = context;
+ OCA.Onlyoffice.context.fileName = fileName;
};
OCA.Onlyoffice.FileConvertClick = function (fileName, context) {
@@ -159,6 +227,37 @@
}
};
+ OCA.Onlyoffice.onRequestSaveAs = function (saveData) {
+ OC.dialogs.filepicker(t(OCA.Onlyoffice.AppName, "Save as"),
+ function (fileDir) {
+ saveData.dir = fileDir;
+ $("#onlyofficeFrame")[0].contentWindow.OCA.Onlyoffice.editorSaveAs(saveData);
+ },
+ false,
+ "httpd/unix-directory");
+ };
+
+ OCA.Onlyoffice.onRequestInsertImage = function (imageMimes) {
+ OC.dialogs.filepicker(t(OCA.Onlyoffice.AppName, "Insert image"),
+ $("#onlyofficeFrame")[0].contentWindow.OCA.Onlyoffice.editorInsertImage,
+ false,
+ imageMimes);
+ };
+
+ OCA.Onlyoffice.onRequestMailMergeRecipients = function (recipientMimes) {
+ OC.dialogs.filepicker(t(OCA.Onlyoffice.AppName, "Select recipients"),
+ $("#onlyofficeFrame")[0].contentWindow.OCA.Onlyoffice.editorSetRecipient,
+ false,
+ recipientMimes);
+ };
+
+ OCA.Onlyoffice.onRequestCompareFile = function (revisedMimes) {
+ OC.dialogs.filepicker(t(OCA.Onlyoffice.AppName, "Select file to compare"),
+ $("#onlyofficeFrame")[0].contentWindow.OCA.Onlyoffice.editorSetRevised,
+ false,
+ revisedMimes);
+ };
+
OCA.Onlyoffice.FileList = {
attach: function (fileList) {
if (fileList.id == "trashbin") {
@@ -282,6 +381,36 @@
}
};
+ window.addEventListener("message", function(event) {
+ if ($("#onlyofficeFrame")[0].contentWindow !== event.source
+ || !event.data["method"]) {
+ return;
+ }
+ switch (event.data.method) {
+ case "editorRequestClose":
+ OCA.Onlyoffice.CloseEditor();
+ break;
+ case "editorRequestSharingSettings":
+ OCA.Onlyoffice.OpenShareDialog();
+ break;
+ case "editorRequestSaveAs":
+ OCA.Onlyoffice.onRequestSaveAs(event.data.param);
+ break;
+ case "editorRequestInsertImage":
+ OCA.Onlyoffice.onRequestInsertImage(event.data.param);
+ break;
+ case "editorRequestMailMergeRecipients":
+ OCA.Onlyoffice.onRequestMailMergeRecipients(event.data.param);
+ break;
+ case "editorRequestCompareFile":
+ OCA.Onlyoffice.onRequestCompareFile(event.data.param);
+ break;
+ case "editorShowHeaderButton":
+ OCA.Onlyoffice.ShowHeaderButton();
+ break;
+ }
+ }, false);
+
$(document).ready(initPage)
})(OCA);
diff --git a/l10n/de.js b/l10n/de.js
index a2821ec..10899c6 100644
--- a/l10n/de.js
+++ b/l10n/de.js
@@ -77,6 +77,7 @@ OC.L10N.register(
"Show watermark for download hidden shares" : "Wasserzeichen auf ‘Download verbergen’ Freigaben anzeigen",
"Show watermark for read only link shares" : "Wasserzeichen auf schreibgeschützten Link-Freigaben anzeigen",
"Show watermark on link shares with specific system tags" : "Wasserzeichen auf Link-Freigaben mit bestimmten System-Tags anzeigen",
- "Select tag" : "Wähle einen Tag"
+ "Select tag" : "Wähle einen Tag",
+ "Select file to compare" : "Datei zum Vergleich auswählen"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/de.json b/l10n/de.json
index 9f29756..df18125 100644
--- a/l10n/de.json
+++ b/l10n/de.json
@@ -75,6 +75,7 @@
"Show watermark for download hidden shares" : "Wasserzeichen auf ‘Download verbergen’ Freigaben anzeigen",
"Show watermark for read only link shares" : "Wasserzeichen auf schreibgeschützten Link-Freigaben anzeigen",
"Show watermark on link shares with specific system tags" : "Wasserzeichen auf Link-Freigaben mit bestimmten System-Tags anzeigen",
- "Select tag" : "Wähle einen Tag"
+ "Select tag" : "Wähle einen Tag",
+ "Select file to compare" : "Datei zum Vergleich auswählen"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/l10n/de_DE.js b/l10n/de_DE.js
index fb5c34a..96f994d 100644
--- a/l10n/de_DE.js
+++ b/l10n/de_DE.js
@@ -77,6 +77,7 @@ OC.L10N.register(
"Show watermark for download hidden shares" : "Wasserzeichen auf ‘Download verbergen’ Freigaben anzeigen",
"Show watermark for read only link shares" : "Wasserzeichen auf schreibgeschützten Link-Freigaben anzeigen",
"Show watermark on link shares with specific system tags" : "Wasserzeichen auf Link-Freigaben mit bestimmten System-Tags anzeigen",
- "Select tag" : "Wählen Sie ein Tag"
+ "Select tag" : "Wählen Sie ein Tag",
+ "Select file to compare" : "Datei zum Vergleich auswählen"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/de_DE.json b/l10n/de_DE.json
index 0df7f0c..9b3d891 100644
--- a/l10n/de_DE.json
+++ b/l10n/de_DE.json
@@ -75,6 +75,7 @@
"Show watermark for download hidden shares" : "Wasserzeichen auf ‘Download verbergen’ Freigaben anzeigen",
"Show watermark for read only link shares" : "Wasserzeichen auf schreibgeschützten Link-Freigaben anzeigen",
"Show watermark on link shares with specific system tags" : "Wasserzeichen auf Link-Freigaben mit bestimmten System-Tags anzeigen",
- "Select tag" : "Wählen Sie ein Tag"
+ "Select tag" : "Wählen Sie ein Tag",
+ "Select file to compare" : "Datei zum Vergleich auswählen"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/l10n/es.js b/l10n/es.js
index 5825821..d1f7e37 100644
--- a/l10n/es.js
+++ b/l10n/es.js
@@ -60,6 +60,7 @@ OC.L10N.register(
"Select recipients" : "Seleccionar destinatarios",
"Secure view enables you to secure documents by embedding a watermark" : "La vista segura permite asegurar documentos mediante la inserción de una marca de agua en ellos",
"Supported placeholders" : "Marcadores soportados",
- "Select tag" : "Seleccionar etiqueta"
+ "Select tag" : "Seleccionar etiqueta",
+ "Select file to compare" : "Seleccione un archivo para comparar"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/es.json b/l10n/es.json
index 311743b..2c9598c 100644
--- a/l10n/es.json
+++ b/l10n/es.json
@@ -58,6 +58,7 @@
"Select recipients" : "Seleccionar destinatarios",
"Secure view enables you to secure documents by embedding a watermark" : "La vista segura permite asegurar documentos mediante la inserción de una marca de agua en ellos",
"Supported placeholders" : "Marcadores soportados",
- "Select tag" : "Seleccionar etiqueta"
+ "Select tag" : "Seleccionar etiqueta",
+ "Select file to compare" : "Seleccione un archivo para comparar"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/l10n/fr.js b/l10n/fr.js
index 8236b78..0ecc924 100644
--- a/l10n/fr.js
+++ b/l10n/fr.js
@@ -58,6 +58,7 @@ OC.L10N.register(
"File saved" : "Le fichier a été enregistré",
"Insert image" : "Insérer une image",
"Select recipients" : "Sélectionner les destinataires",
- "Select tag" : "Sélectionner une étiquette"
+ "Select tag" : "Sélectionner une étiquette",
+ "Select file to compare" : "Sélectionner fichier à comparer"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/fr.json b/l10n/fr.json
index 2e4ed18..6c609af 100644
--- a/l10n/fr.json
+++ b/l10n/fr.json
@@ -56,6 +56,7 @@
"File saved" : "Le fichier a été enregistré",
"Insert image" : "Insérer une image",
"Select recipients" : "Sélectionner les destinataires",
- "Select tag" : "Sélectionner une étiquette"
+ "Select tag" : "Sélectionner une étiquette",
+ "Select file to compare" : "Sélectionner fichier à comparer"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
diff --git a/l10n/pt_BR.js b/l10n/pt_BR.js
index a765e07..99aa6f8 100644
--- a/l10n/pt_BR.js
+++ b/l10n/pt_BR.js
@@ -60,6 +60,7 @@ OC.L10N.register(
"Select recipients" : "Selecione os destinatários",
"Secure view enables you to secure documents by embedding a watermark" : "A visualização segura permite proteger documentos incorporando uma marca d'água",
"Supported placeholders" : "Espaços reservados suportados",
- "Select tag" : "Selecionar etiqueta"
+ "Select tag" : "Selecionar etiqueta",
+ "Select file to compare" : "Selecionar arquivo para comparar"
},
"nplurals=2; plural=(n != 1);");
diff --git a/l10n/pt_BR.json b/l10n/pt_BR.json
index 1ea90a4..f0181e9 100644
--- a/l10n/pt_BR.json
+++ b/l10n/pt_BR.json
@@ -58,6 +58,7 @@
"Select recipients" : "Selecione os destinatários",
"Secure view enables you to secure documents by embedding a watermark" : "A visualização segura permite proteger documentos incorporando uma marca d'água",
"Supported placeholders" : "Espaços reservados suportados",
- "Select tag" : "Selecionar etiqueta"
+ "Select tag" : "Selecionar etiqueta",
+ "Select file to compare" : "Selecionar arquivo para comparar"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
diff --git a/l10n/ru.js b/l10n/ru.js
index 68293b4..779b7b9 100644
--- a/l10n/ru.js
+++ b/l10n/ru.js
@@ -77,6 +77,7 @@ OC.L10N.register(
"Show watermark for download hidden shares" : "Отображать водяной знак при доступе без скачивания",
"Show watermark for read only link shares" : "Отображать водяной знак при доступе только на чтение по ссылке",
"Show watermark on link shares with specific system tags" : "Отображать водяной знак при доступе по ссылке с определенными системными метками",
- "Select tag" : "Выберите метку"
+ "Select tag" : "Выберите метку",
+ "Select file to compare" : "Выбрать файл для сравнения"
},
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);");
diff --git a/l10n/ru.json b/l10n/ru.json
index 422cb05..7f393ce 100644
--- a/l10n/ru.json
+++ b/l10n/ru.json
@@ -75,6 +75,7 @@
"Show watermark for download hidden shares" : "Отображать водяной знак при доступе без скачивания",
"Show watermark for read only link shares" : "Отображать водяной знак при доступе только на чтение по ссылке",
"Show watermark on link shares with specific system tags" : "Отображать водяной знак при доступе по ссылке с определенными системными метками",
- "Select tag" : "Выберите метку"
+ "Select tag" : "Выберите метку",
+ "Select file to compare" : "Выбрать файл для сравнения"
},"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
} \ No newline at end of file
diff --git a/lib/appconfig.php b/lib/appconfig.php
index b90f844..2560b6f 100644
--- a/lib/appconfig.php
+++ b/lib/appconfig.php
@@ -239,6 +239,20 @@ class AppConfig {
public $_customization_logo = "customization_logo";
/**
+ * The config key for the zoom
+ *
+ * @var string
+ */
+ public $_customization_zoom = "customization_zoom";
+
+ /**
+ * The config key for the autosave
+ *
+ * @var string
+ */
+ public $_customization_autosave = "customization_autosave";
+
+ /**
* @param string $AppName - application name
*/
public function __construct($AppName) {
diff --git a/lib/directeditor.php b/lib/directeditor.php
new file mode 100644
index 0000000..7d73ff7
--- /dev/null
+++ b/lib/directeditor.php
@@ -0,0 +1,275 @@
+<?php
+/**
+ *
+ * (c) Copyright Ascensio System SIA 2019
+ *
+ * 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
+ * (AGPL) version 3 as published by the Free Software Foundation.
+ * In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
+ * that Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
+ *
+ * This program is distributed WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * For details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
+ *
+ * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha street, Riga, Latvia, EU, LV-1050.
+ *
+ * The interactive user interfaces in modified source and object code versions of the Program
+ * must display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
+ *
+ * Pursuant to Section 7(b) of the License you must retain the original Product logo when distributing the program.
+ * Pursuant to Section 7(e) we decline to grant you any rights under trademark law for use of our trademarks.
+ *
+ * All the Product's GUI elements, including illustrations and icon sets, as well as technical
+ * writing content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International.
+ * See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
+ *
+ */
+
+namespace OCA\Onlyoffice;
+
+use OCP\AppFramework\Http\ContentSecurityPolicy;
+use OCP\AppFramework\Http\NotFoundResponse;
+use OCP\AppFramework\Http\Response;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\DirectEditing\IEditor;
+use OCP\DirectEditing\IToken;
+use OCP\IL10N;
+use OCP\ILogger;
+use OCP\IURLGenerator;
+
+use OCA\Onlyoffice\AppConfig;
+use OCA\Onlyoffice\Crypt;
+use OCA\Onlyoffice\FileCreator;
+
+/**
+ * Direct Editor
+ *
+ * @package OCA\Onlyoffice
+ */
+class DirectEditor implements IEditor {
+
+ /**
+ * Application name
+ *
+ * @var string
+ */
+ private $appName;
+
+ /**
+ * Url generator service
+ *
+ * @var IURLGenerator
+ */
+ private $urlGenerator;
+
+ /**
+ * l10n service
+ *
+ * @var IL10N
+ */
+ private $trans;
+
+ /**
+ * Logger
+ *
+ * @var ILogger
+ */
+ private $logger;
+
+ /**
+ * Application configuration
+ *
+ * @var OCA\Onlyoffice\AppConfig
+ */
+ private $config;
+
+ /**
+ * Hash generator
+ *
+ * @var OCA\Onlyoffice\Crypt
+ */
+ private $crypt;
+
+ /**
+ * @param string $AppName - application name
+ * @param IURLGenerator $urlGenerator - url generator service
+ * @param IL10N $trans - l10n service
+ * @param ILogger $logger - logger
+ * @param OCA\Onlyoffice\AppConfig $config - application configuration
+ * @param OCA\Onlyoffice\Crypt $crypt - hash generator
+ */
+ public function __construct($AppName,
+ IURLGenerator $urlGenerator,
+ IL10N $trans,
+ ILogger $logger,
+ AppConfig $config,
+ Crypt $crypt) {
+ $this->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();
+ $formats = $this->config->FormatsSetting();
+ foreach ($formats as $format => $setting) {
+ if (array_key_exists("edit", $setting) && $setting["edit"]
+ && array_key_exists("def", $setting) && $setting["def"]) {
+ array_push($mimes, $setting["mime"]);
+ }
+ }
+
+ return $mimes;
+ }
+
+ /**
+ * A list of mimetypes that can be opened in the editor optionally
+ *
+ * @return array
+ */
+ public function getMimetypesOptional(): array {
+ $mimes = array();
+ $formats = $this->config->FormatsSetting();
+ foreach ($formats as $format => $setting) {
+ if (array_key_exists("edit", $setting) && $setting["edit"]
+ && (!array_key_exists("def", $setting) || !$setting["def"])) {
+ array_push($mimes, $setting["mime"]);
+ }
+ }
+
+ return $mimes;
+ }
+
+ /**
+ * Return a list of file creation options to be presented to the user
+ *
+ * @return array of ACreateFromTemplate|ACreateEmpty
+ */
+ public function getCreators(): 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 impelement 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();
+ $this->logger->debug("DirectEditor open: $fileId", array("app" => $this->appName));
+
+ $documentServerUrl = $this->config->GetDocumentServerUrl();
+
+ if (empty($documentServerUrl)) {
+ $this->logger->error("documentServerUrl is empty", array("app" => $this->appName));
+ return $this->renderError($this->trans->t("ONLYOFFICE app is not configured. Please contact admin"));
+ }
+
+ $userId = $token->getUser();
+ $directToken = $this->crypt->GetHash([
+ "userId" => $userId,
+ "fileId" => $fileId,
+ "action" => "direct",
+ "iat" => time(),
+ "exp" => time() + 30
+ ]);
+
+ $filePath = $file->getPath();
+ $filePath = preg_replace("/^" . $userId . "/", "", $filePath);
+ $params = [
+ "documentServerUrl" => $documentServerUrl,
+ "fileId" => null,
+ "filePath" => $filePath,
+ "shareToken" => null,
+ "directToken" => $directToken
+ ];
+
+ $response = new TemplateResponse($this->appName, "editor", $params, "base");
+
+ $csp = new ContentSecurityPolicy();
+ $csp->allowInlineScript(true);
+
+ if (preg_match("/^https?:\/\//i", $documentServerUrl)) {
+ $csp->addAllowedScriptDomain($documentServerUrl);
+ $csp->addAllowedFrameDomain($documentServerUrl);
+ } else {
+ $csp->addAllowedFrameDomain($this->urlGenerator->getAbsoluteURL("/"));
+ }
+ $response->setContentSecurityPolicy($csp);
+
+ return $response;
+ } catch (\Exception $e) {
+ $this->logger->error("DirectEditor open: " . $e->getMessage(), array("app" => $this->appName));
+ return $this->renderError($e->getMessage());
+ }
+ }
+
+ /**
+ * Print error page
+ *
+ * @param string $error - error message
+ * @param string $hint - error hint
+ *
+ * @return TemplateResponse
+ */
+ private function renderError($error, $hint = "") {
+ return new TemplateResponse("", "error", array(
+ "errors" => array(
+ array(
+ "error" => $error,
+ "hint" => $hint
+ )
+ )
+ ), "error");
+ }
+}
diff --git a/lib/filecreator.php b/lib/filecreator.php
new file mode 100644
index 0000000..788b172
--- /dev/null
+++ b/lib/filecreator.php
@@ -0,0 +1,194 @@
+<?php
+/**
+ *
+ * (c) Copyright Ascensio System SIA 2019
+ *
+ * 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
+ * (AGPL) version 3 as published by the Free Software Foundation.
+ * In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
+ * that Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
+ *
+ * This program is distributed WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * For details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
+ *
+ * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha street, Riga, Latvia, EU, LV-1050.
+ *
+ * The interactive user interfaces in modified source and object code versions of the Program
+ * must display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
+ *
+ * Pursuant to Section 7(b) of the License you must retain the original Product logo when distributing the program.
+ * Pursuant to Section 7(e) we decline to grant you any rights under trademark law for use of our trademarks.
+ *
+ * All the Product's GUI elements, including illustrations and icon sets, as well as technical
+ * writing content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International.
+ * See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
+ *
+ */
+
+namespace OCA\Onlyoffice;
+
+use OCP\DirectEditing\ACreateEmpty;
+use OCP\Files\File;
+use OCP\IL10N;
+use OCP\ILogger;
+
+/**
+ * File creator
+ *
+ * @package OCA\Onlyoffice
+ */
+class FileCreator extends ACreateEmpty {
+
+ /**
+ * Application name
+ *
+ * @var string
+ */
+ private $appName;
+
+ /**
+ * l10n service
+ *
+ * @var IL10N
+ */
+ private $trans;
+
+ /**
+ * Logger
+ *
+ * @var ILogger
+ */
+ private $logger;
+
+ /**
+ * Format for creation
+ *
+ * @var string
+ */
+ private $format;
+
+ /**
+ * @param string $AppName - application name
+ * @param IL10N $trans - l10n service
+ * @param ILogger $logger - logger
+ * @param string $format - format for creation
+ */
+ public function __construct($AppName,
+ IL10N $trans,
+ ILogger $logger,
+ $format) {
+ $this->appName = $AppName;
+ $this->trans = $trans;
+ $this->logger = $logger;
+ $this->format = $format;
+ }
+
+ /**
+ * Unique id for the creator to filter templates
+ *
+ * @return string
+ */
+ public function getId(): string {
+ return $this->appName . "_" . $this->format;
+ }
+
+ /**
+ * Descriptive name for the create action
+ *
+ * @return string
+ */
+ public function getName(): string {
+ switch ($this->format) {
+ case "xlsx":
+ return $this->trans->t("Spreadsheet");
+ case "pptx":
+ return $this->trans->t("Presentation");
+ }
+ return $this->trans->t("Document");
+ }
+
+ /**
+ * Default file extension for the new file
+ *
+ * @return string
+ */
+ public function getExtension(): string {
+ return $this->format;
+ }
+
+ /**
+ * Mimetype of the resulting created file
+ *
+ * @return array
+ */
+ public function getMimetype(): string {
+ switch ($this->format) {
+ case "xlsx":
+ return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
+ case "pptx":
+ return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
+ }
+ return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
+ }
+
+ /**
+ * Add content when creating empty files
+ *
+ * @param File $file - empty file
+ * @param string $creatorId - creator id
+ * @param string $templateId - teamplate id
+ */
+ public function create(File $file, string $creatorId = null, string $templateId = null): void {
+ $this->logger->debug("FileCreator: " . $file->getId() . " " . $file->getName() . " $creatorId $templateId", array("app" => $this->appName));
+
+ $fileName = $file->getName();
+ $template = self::GetTemplate($fileName);
+
+ if (!$template) {
+ $this->logger->error("FileCreator: Template for file creation not found: $templatePath", array("app" => $this->appName));
+ return;
+ }
+
+ try {
+ $file->putContent($template);
+ } catch (NotPermittedException $e) {
+ $this->logger->error("FileCreator: Can't create file: $name", array("app" => $this->appName));
+ }
+ }
+
+ /**
+ * Get template
+ *
+ * @param string $name - file name
+ *
+ * @return string
+ */
+ public static function GetTemplate(string $name) {
+ $ext = strtolower("." . pathinfo($name, PATHINFO_EXTENSION));
+
+ $lang = \OC::$server->getL10NFactory("")->get("")->getLanguageCode();
+
+ $templatePath = self::getTemplatePath($lang, $ext);
+ if (!file_exists($templatePath)) {
+ $lang = "en";
+ $templatePath = self::getTemplatePath($lang, $ext);
+ }
+
+ $template = file_get_contents($templatePath);
+ return $template;
+ }
+
+ /**
+ * Get template path
+ *
+ * @param string $lang - language
+ * @param string $ext - file extension
+ *
+ * @return string
+ */
+ private static function GetTemplatePath(string $lang, string $ext) {
+ return dirname(__DIR__) . DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR . $lang . DIRECTORY_SEPARATOR . "new" . $ext;
+ }
+}
diff --git a/templates/editor.php b/templates/editor.php
index ced8968..a9642dd 100644
--- a/templates/editor.php
+++ b/templates/editor.php
@@ -30,11 +30,19 @@
style("onlyoffice", "editor");
script("onlyoffice", "desktop");
script("onlyoffice", "editor");
+ if (!empty($_["directToken"])) {
+ script("onlyoffice", "directeditor");
+ }
?>
<div id="app">
- <div id="iframeEditor" data-id="<?php p($_["fileId"]) ?>" data-path="<?php p($_["filePath"]) ?>" data-sharetoken="<?php p($_["shareToken"]) ?>"></div>
+ <div id="iframeEditor"
+ data-id="<?php p($_["fileId"]) ?>"
+ data-path="<?php p($_["filePath"]) ?>"
+ data-sharetoken="<?php p($_["shareToken"]) ?>"
+ data-directtoken="<?php p($_["directToken"]) ?>"
+ data-inframe="<?php p($_["inframe"]) ?>"></div>
<?php if (!empty($_["documentServerUrl"])) { ?>
<script nonce="<?php p(base64_encode($_["requesttoken"])) ?>"