From 09aa42eb653597fa02fdf69012ec57ecce1126fd Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Mon, 6 Mar 2017 11:03:41 +0300 Subject: Document Server v4.2 (Issue #13) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f00249e..de82948 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ The app will create an item in the `new` (+) menu to create **Document**, **Spre ## Installing ONLYOFFICE Document Server -You will need an instance of ONLYOFFICE Document Server that is resolvable and connectable both from ownCloud/Nextcloud and any end clients (version 3.0 and later are supported for use with the app). If that is not the case, use the official ONLYOFFICE Document Server documetnations page: [Document Server for Linux](http://helpcenter.onlyoffice.com/server/linux/document/linux-installation.aspx). ONLYOFFICE Document Server must also be able to POST to ownCloud directly. +You will need an instance of ONLYOFFICE Document Server that is resolvable and connectable both from ownCloud/Nextcloud and any end clients (version 4.2 and later are supported for use with the app). If that is not the case, use the official ONLYOFFICE Document Server documetnations page: [Document Server for Linux](http://helpcenter.onlyoffice.com/server/linux/document/linux-installation.aspx). ONLYOFFICE Document Server must also be able to POST to ownCloud/Nextcloud directly. The easiest way to start an instance of ONLYOFFICE Document Server is to use [Docker](https://github.com/ONLYOFFICE/Docker-DocumentServer). -- cgit v1.2.3 From 6c3f7b188f56c1aa68ff9190020adde59255de1d Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Mon, 6 Mar 2017 11:04:22 +0300 Subject: Check REQUEST_URI (Issue #12) --- appinfo/application.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appinfo/application.php b/appinfo/application.php index ffb400a..9aab16d 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -60,7 +60,8 @@ class Application extends App { $this->crypt = new Crypt($this->appConfig); // Default script and style if configured - if (!empty($this->appConfig->GetDocumentServerUrl())) + if (!empty($this->appConfig->GetDocumentServerUrl()) + && array_key_exists("REQUEST_URI", \OC::$server->getRequest()->server)) { $url = \OC::$server->getRequest()->server["REQUEST_URI"]; -- cgit v1.2.3 From feb642a5f7619c139da64c24145f96f9f9171f6d Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Mon, 27 Mar 2017 15:56:32 +0300 Subject: Nextcloud categories --- appinfo/info.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/appinfo/info.xml b/appinfo/info.xml index 212e1c1..e0b350e 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -15,6 +15,11 @@ https://api.onlyoffice.com/editors/owncloud + files + integration + office + organization + tools tool https://www.onlyoffice.com https://github.com/ONLYOFFICE/onlyoffice-owncloud/issues -- cgit v1.2.3 From f232414d9e56090f6a09ba7ed43c976cf468c137 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Mon, 27 Mar 2017 16:00:55 +0300 Subject: author attribute not supported in ownCloud 9.1.4 --- appinfo/info.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appinfo/info.xml b/appinfo/info.xml index e0b350e..02a4547 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -6,7 +6,7 @@ ownCloud ONLYOFFICE integration app ONLYOFFICE integration app enables users to edit Office documents within ONLYOFFICE from OwnCloud. 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 OwnCloud. AGPL - Ascensio System SIA + Ascensio System SIA 1.0.1 Onlyoffice -- cgit v1.2.3 From d7354780345b99c089c70ef51a92a7679cfc685a Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Tue, 28 Mar 2017 18:42:22 +0300 Subject: logging config --- lib/appconfig.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/appconfig.php b/lib/appconfig.php index b97cfc9..d58da9e 100644 --- a/lib/appconfig.php +++ b/lib/appconfig.php @@ -27,6 +27,7 @@ namespace OCA\Onlyoffice; use OCP\IConfig; +use OCP\ILogger; /** * Application configutarion @@ -49,6 +50,13 @@ class AppConfig { */ private $config; + /** + * Logger + * + * @var OCP\ILogger + */ + private $logger; + /** * The config key for the document server address * @@ -67,9 +75,11 @@ class AppConfig { * @param string $AppName application name */ public function __construct($AppName) { - + $this->appName = $AppName; + $this->config = \OC::$server->getConfig(); + $this->logger = \OC::$server->getLogger(); } /** @@ -82,6 +92,9 @@ class AppConfig { if (strlen($documentServer) > 0 && !preg_match("/^https?:\/\//i", $documentServer)) { $documentServer = "http://" . $documentServer; } + + $this->logger->info("SetDocumentServerUrl: " . $documentServer, array("app" => $this->appName)); + $this->config->setAppValue($this->appName, $this->_documentserver, $documentServer); $this->DropSKey(); } -- cgit v1.2.3 From 133c19729caace2dbe79687a49c7c1eff7cda5d3 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Tue, 28 Mar 2017 18:43:06 +0300 Subject: logging editor page --- appinfo/application.php | 5 +++++ controller/editorcontroller.php | 32 +++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/appinfo/application.php b/appinfo/application.php index 9aab16d..241b1a3 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -87,6 +87,10 @@ class Application extends App { return $c->query("ServerContainer")->getUserSession(); }); + $container->registerService("Logger", function($c) { + return $c->query("ServerContainer")->getLogger(); + }); + // Controllers $container->registerService("SettingsController", function($c) { @@ -105,6 +109,7 @@ class Application extends App { $c->query("UserSession")->getUser(), $c->query("ServerContainer")->getURLGenerator(), $c->query("L10N"), + $c->query("Logger"), $this->appConfig, $this->crypt ); diff --git a/controller/editorcontroller.php b/controller/editorcontroller.php index 5828e6d..b0e894e 100644 --- a/controller/editorcontroller.php +++ b/controller/editorcontroller.php @@ -34,6 +34,7 @@ use OCP\AutoloadNotAllowedException; use OCP\Files\FileInfo; use OCP\Files\IRootFolder; use OCP\IL10N; +use OCP\ILogger; use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUser; @@ -82,6 +83,13 @@ class EditorController extends Controller { */ private $trans; + /** + * Logger + * + * @var OCP\ILogger + */ + private $logger; + /** * Application configuration * @@ -102,7 +110,8 @@ class EditorController extends Controller { * @param IRootFolder $root root folder * @param IUser $user current user * @param IURLGenerator $urlGenerator url generator service - * @param IL10N $l10n l10n service + * @param IL10N $trans l10n service + * @param ILogger $logger logger * @param OCA\Onlyoffice\AppConfig $config application configuration * @param OCA\Onlyoffice\Crypt $crypt hash generator */ @@ -112,6 +121,7 @@ class EditorController extends Controller { IUser $user, IURLGenerator $urlGenerator, IL10N $trans, + ILogger $logger, AppConfig $config, Crypt $crypt ) { @@ -121,6 +131,7 @@ class EditorController extends Controller { $this->root = $root; $this->urlGenerator = $urlGenerator; $this->trans = $trans; + $this->logger = $logger; $this->config = $config; $this->crypt = $crypt; } @@ -142,9 +153,11 @@ class EditorController extends Controller { $folder = $userFolder->get($dir); if ($folder === NULL) { + $this->logger->info("Folder for file creation was not found: " . $dir, array("app" => $this->appName)); return ["error" => $this->trans->t("The required folder was not found")]; } if (!$folder->isCreatable()) { + $this->logger->info("Folder for file creation without permission: " . $dir, array("app" => $this->appName)); return ["error" => $this->trans->t("You don't have enough permission to create")]; } @@ -155,17 +168,20 @@ class EditorController extends Controller { $template = file_get_contents($templatePath); if (!$template) { + $this->logger->info("Template for file creation not found: " . $templatePath, array("app" => $this->appName)); return ["error" => $this->trans->t("Template not found")]; } $view = Filesystem::getView(); if (!$view->file_put_contents($filePath, $template)) { + $this->logger->error("Can't create file: " . $filePath, array("app" => $this->appName)); return ["error" => $this->trans->t("Can't create file")]; } $fileInfo = $view->getFileInfo($filePath); if ($fileInfo === false) { + $this->logger->info("File not found: " . $filePath, array("app" => $this->appName)); return ["error" => $this->trans->t("File not found")]; } @@ -186,6 +202,7 @@ class EditorController extends Controller { list ($file, $error) = $this->getFile($fileId); if (isset($error)) { + $this->logger->error("Convertion: " . $fileId . " " . $error, array("app" => $this->appName)); return ["error" => $error]; } @@ -193,10 +210,12 @@ class EditorController extends Controller { $ext = pathinfo($fileName, PATHINFO_EXTENSION); $format = $this->config->formats[$ext]; if (!isset($format)) { + $this->logger->info("Format for convertion not supported: " . $fileName, array("app" => $this->appName)); return ["error" => $this->trans->t("Format do not supported")]; } - if(!isset($format["conv"]) || $format["conv"] !== TRUE) { + if (!isset($format["conv"]) || $format["conv"] !== TRUE) { + $this->logger->debug("Conversion not required: " . $fileName, array("app" => $this->appName)); return ["error" => $this->trans->t("Conversion not required")]; } @@ -217,6 +236,7 @@ class EditorController extends Controller { try { $documentService->GetConvertedUri($fileUrl, $ext, $internalExtension, $key, FALSE, $newFileUri); } catch (\Exception $e) { + $this->logger->error("GetConvertedUri: " . $fileId . " " . $e->getMessage(), array("app" => $this->appName)); return ["error" => $e->getMessage()]; } @@ -234,17 +254,20 @@ class EditorController extends Controller { $newFilePath = $newFolderPath . DIRECTORY_SEPARATOR . $newFileName; if (($newData = file_get_contents($newFileUri)) === FALSE){ + $this->logger->error("Failed download converted file: " . $newFileUri, array("app" => $this->appName)); return ["error" => $this->trans->t("Failed download converted file")]; } $view = Filesystem::getView(); if (!$view->file_put_contents($newFilePath, $newData)) { + $this->logger->error("Can't create file after convertion: " . $newFilePath, array("app" => $this->appName)); return ["error" => $this->trans->t("Can't create file")]; } $fileInfo = $view->getFileInfo($newFilePath); if ($fileInfo === false) { + $this->logger->info("File not found: " . $newFilePath, array("app" => $this->appName)); return ["error" => $this->trans->t("File not found")]; } @@ -291,6 +314,7 @@ class EditorController extends Controller { list ($file, $error) = $this->getFile($fileId); if (isset($error)) { + $this->logger->error("Convertion: " . $fileId . " " . $error, array("app" => $this->appName)); return ["error" => $error]; } @@ -298,12 +322,14 @@ class EditorController extends Controller { $ext = pathinfo($fileName, PATHINFO_EXTENSION); $format = $this->config->formats[$ext]; if (!isset($format)) { + $this->logger->info("Format do not supported for editing: " . $fileName, array("app" => $this->appName)); return ["error" => $this->trans->t("Format do not supported")]; } $documentServerUrl = $this->config->GetDocumentServerUrl(); if (empty($documentServerUrl)) { + $this->logger->error("documentServerUrl is empty", array("app" => $this->appName)); return ["error" => $this->trans->t("ONLYOFFICE app not configured. Please contact admin")]; } @@ -350,7 +376,7 @@ class EditorController extends Controller { } $files = $this->root->getById($fileId); - if(empty($files)) { + if (empty($files)) { return [NULL, $this->trans->t("File not found")]; } $file = $files[0]; -- cgit v1.2.3 From 54f8cbccfa1adbf621c6ccc4404f0d2825011d7a Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Tue, 28 Mar 2017 19:24:41 +0300 Subject: logging callback --- appinfo/application.php | 1 + controller/callbackcontroller.php | 28 +++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/appinfo/application.php b/appinfo/application.php index 241b1a3..1870279 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -123,6 +123,7 @@ class Application extends App { $c->query("UserSession"), $c->query("ServerContainer")->getUserManager(), $c->query("L10N"), + $c->query("Logger"), $this->appConfig, $this->crypt ); diff --git a/controller/callbackcontroller.php b/controller/callbackcontroller.php index 0eeeb3c..4c3e182 100644 --- a/controller/callbackcontroller.php +++ b/controller/callbackcontroller.php @@ -31,6 +31,7 @@ use OCP\AppFramework\Http; use OCP\Files\File; use OCP\Files\IRootFolder; use OCP\IL10N; +use OCP\ILogger; use OCP\IRequest; use OCP\IUserManager; use OCP\IUserSession; @@ -76,6 +77,13 @@ class CallbackController extends Controller { */ private $trans; + /** + * Logger + * + * @var OCP\ILogger + */ + private $logger; + /** * Application configuration * @@ -109,7 +117,9 @@ class CallbackController extends Controller { * @param IRootFolder $root root folder * @param IUserSession $userSession user session * @param IUserManager $userManager user manager - * @param IL10N $l10n l10n 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, @@ -118,6 +128,7 @@ class CallbackController extends Controller { IUserSession $userSession, IUserManager $userManager, IL10N $trans, + ILogger $logger, AppConfig $config, Crypt $crypt ) { @@ -127,6 +138,7 @@ class CallbackController extends Controller { $this->userSession = $userSession; $this->userManager = $userManager; $this->trans = $trans; + $this->logger = $logger; $this->config = $config; $this->crypt = $crypt; } @@ -148,9 +160,11 @@ class CallbackController extends Controller { $hashData = $this->crypt->ReadHash($doc); if ($hashData === NULL) { + $this->logger->info("Download with empty or not correct hash", array("app" => $this->appName)); return new ErrorResponse(Http::STATUS_FORBIDDEN, $this->trans->t("Access deny")); } if ($hashData->action !== "download") { + $this->logger->info("Download with other action", array("app" => $this->appName)); return new ErrorResponse(Http::STATUS_BAD_REQUEST, $this->trans->t("Invalid request")); } @@ -158,18 +172,21 @@ class CallbackController extends Controller { $ownerId = $hashData->ownerId; $files = $this->root->getUserFolder($ownerId)->getById($fileId); - if(empty($files)) { + if (empty($files)) { + $this->logger->info("Files for download not found: " . $fileId, array("app" => $this->appName)); return new ErrorResponse(Http::STATUS_NOT_FOUND, $this->trans->t("Files not found")); } $file = $files[0]; if (! $file instanceof File) { + $this->logger->info("File for download not found: " . $fileId, array("app" => $this->appName)); return new ErrorResponse(Http::STATUS_NOT_FOUND, $this->trans->t("File not found")); } try { return new DownloadResponse($file); } catch(\OCP\Files\NotPermittedException $e) { + $this->logger->info("Download Not permitted: " . $fileId . " " . $e->getMessage(), array("app" => $this->appName)); return new ErrorResponse(Http::STATUS_FORBIDDEN, $this->trans->t("Not permitted")); } return new ErrorResponse(Http::STATUS_INTERNAL_SERVER_ERROR, $this->trans->t("Download failed")); @@ -194,9 +211,11 @@ class CallbackController extends Controller { $hashData = $this->crypt->ReadHash($doc); if ($hashData === NULL) { + $this->logger->info("Track with empty or not correct hash", array("app" => $this->appName)); return ["message" => $this->trans->t("Access deny")]; } if ($hashData->action !== "track") { + $this->logger->info("Track with other action", array("app" => $this->appName)); return ["message" => $this->trans->t("Invalid request")]; } @@ -211,12 +230,14 @@ class CallbackController extends Controller { $ownerId = $hashData->ownerId; $files = $this->root->getUserFolder($ownerId)->getById($fileId); - if(empty($files)) { + if (empty($files)) { + $this->logger->info("Files for track not found: " . $fileId, array("app" => $this->appName)); return ["message" => $this->trans->t("Files not found")]; } $file = $files[0]; if (! $file instanceof File) { + $this->logger->info("File for track not found: " . $fileId, array("app" => $this->appName)); return ["message" => $this->trans->t("File not found")]; } @@ -233,6 +254,7 @@ class CallbackController extends Controller { $documentService->GetConvertedUri($url, $downloadExt, $curExt, $key, FALSE, $newFileUri); $url = $newFileUri; } catch (\Exception $e) { + $this->logger->error("GetConvertedUri in track: " . $url . " " . $e->getMessage(), array("app" => $this->appName)); return ["message" => $e->getMessage()]; } } -- cgit v1.2.3 From 3a43c15848abfa039471a78cbc318262fc95b6a7 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Wed, 29 Mar 2017 17:46:13 +0300 Subject: Change controller arguments (Issue #24) --- appinfo/application.php | 2 +- controller/editorcontroller.php | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/appinfo/application.php b/appinfo/application.php index 1870279..6dd4a39 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -106,7 +106,7 @@ class Application extends App { $c->query("AppName"), $c->query("Request"), $c->query("RootStorage"), - $c->query("UserSession")->getUser(), + $c->query("UserSession"), $c->query("ServerContainer")->getURLGenerator(), $c->query("L10N"), $c->query("Logger"), diff --git a/controller/editorcontroller.php b/controller/editorcontroller.php index b0e894e..0f48326 100644 --- a/controller/editorcontroller.php +++ b/controller/editorcontroller.php @@ -37,7 +37,7 @@ use OCP\IL10N; use OCP\ILogger; use OCP\IRequest; use OCP\IURLGenerator; -use OCP\IUser; +use OCP\IUserSession; use OC\Files\Filesystem; use OC\Files\View; @@ -56,11 +56,11 @@ use OCA\Onlyoffice\DocumentService; class EditorController extends Controller { /** - * Current user + * Current user session * - * @var IUser + * @var IUserSession */ - private $user; + private $userSession; /** * Root folder @@ -86,7 +86,7 @@ class EditorController extends Controller { /** * Logger * - * @var OCP\ILogger + * @var ILogger */ private $logger; @@ -108,7 +108,7 @@ class EditorController extends Controller { * @param string $AppName application name * @param IRequest $request request object * @param IRootFolder $root root folder - * @param IUser $user current user + * @param IUserSession $userSession current user session * @param IURLGenerator $urlGenerator url generator service * @param IL10N $trans l10n service * @param ILogger $logger logger @@ -118,7 +118,7 @@ class EditorController extends Controller { public function __construct($AppName, IRequest $request, IRootFolder $root, - IUser $user, + IUserSession $userSession, IURLGenerator $urlGenerator, IL10N $trans, ILogger $logger, @@ -127,7 +127,7 @@ class EditorController extends Controller { ) { parent::__construct($AppName, $request); - $this->user = $user; + $this->userSession = $userSession; $this->root = $root; $this->urlGenerator = $urlGenerator; $this->trans = $trans; @@ -148,7 +148,7 @@ class EditorController extends Controller { */ public function create($name, $dir) { - $userId = $this->user->getUID(); + $userId = $this->userSession->getUser()->getUID(); $userFolder = $this->root->getUserFolder($userId); $folder = $userFolder->get($dir); @@ -240,7 +240,7 @@ class EditorController extends Controller { return ["error" => $e->getMessage()]; } - $userId = $this->user->getUID(); + $userId = $this->userSession->getUser()->getUID(); $folder = $file->getParent(); if (!$folder->isCreatable()) { $folder = $this->root->getUserFolder($userId); @@ -333,7 +333,7 @@ class EditorController extends Controller { return ["error" => $this->trans->t("ONLYOFFICE app not configured. Please contact admin")]; } - $userId = $this->user->getUID(); + $userId = $this->userSession->getUser()->getUID(); $ownerId = $file->getOwner()->getUID(); try { $this->root->getUserFolder($ownerId); @@ -356,7 +356,7 @@ class EditorController extends Controller { "key" => DocumentService::GenerateRevisionId($key), "url" => $fileUrl, "userId" => $userId, - "userName" => $this->user->getDisplayName(), + "userName" => $this->userSession->getUser()->getDisplayName(), "documentType" => $format["type"] ]; @@ -401,7 +401,7 @@ class EditorController extends Controller { try { $this->root->getUserFolder($ownerId); } catch (NoUserException $e) { - $ownerId = $this->user->getUID(); + $ownerId = $this->userSession->getUser()->getUID(); } $key = $fileId . $file->getMtime(); -- cgit v1.2.3 From b19d022f6c4f533efa1f30270e04a47dba3cb6db Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Mon, 3 Apr 2017 14:02:59 +0300 Subject: checking document service address on save (CommandRequest) --- appinfo/application.php | 4 +- controller/settingscontroller.php | 66 +++++++++++++++++++--- js/settings.js | 7 ++- lib/documentservice.php | 115 ++++++++++++++++++++++++++------------ 4 files changed, 148 insertions(+), 44 deletions(-) diff --git a/appinfo/application.php b/appinfo/application.php index 6dd4a39..568bbb7 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -22,7 +22,7 @@ * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * -*/ + */ namespace OCA\Onlyoffice\AppInfo; @@ -97,6 +97,8 @@ class Application extends App { return new SettingsController( $c->query("AppName"), $c->query("Request"), + $c->query("L10N"), + $c->query("Logger"), $this->appConfig ); }); diff --git a/controller/settingscontroller.php b/controller/settingscontroller.php index 84a70e9..5e04813 100644 --- a/controller/settingscontroller.php +++ b/controller/settingscontroller.php @@ -22,21 +22,38 @@ * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * -*/ + */ namespace OCA\Onlyoffice\Controller; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\TemplateResponse; +use OCP\IL10N; +use OCP\ILogger; use OCP\IRequest; use OCA\Onlyoffice\AppConfig; +use OCA\Onlyoffice\DocumentService; /** * Settings controller for the administration page */ class SettingsController extends Controller { + /** + * l10n service + * + * @var IL10N + */ + private $trans; + + /** + * Logger + * + * @var ILogger + */ + private $logger; + /** * Application configuration * @@ -45,16 +62,22 @@ class SettingsController extends Controller { private $config; /** - * @param string $AppName application name - * @param IRequest $request request object - * @param OCA\Onlyoffice\AppConfig $config application configuration + * @param string $AppName - application name + * @param IRequest $request - request object + * @param IL10N $trans - l10n service + * @param ILogger $logger - logger + * @param OCA\Onlyoffice\AppConfig $config - application configuration */ - public function __construct($AppName, + public function __construct($AppName, IRequest $request, + IL10N $trans, + ILogger $logger, AppConfig $config ) { parent::__construct($AppName, $request); + $this->trans = $trans; + $this->logger = $logger; $this->config = $config; } @@ -71,13 +94,19 @@ class SettingsController extends Controller { /** * Save the document server address * - * @param string $documentserver application name + * @param string $documentserver - document service address * * @return array */ public function settings($documentserver) { $this->config->SetDocumentServerUrl($documentserver); - return ["documentserver" => $this->config->GetDocumentServerUrl()]; + + $error = $this->сheckDocServiceUrl(); + + return [ + "documentserver" => $this->config->GetDocumentServerUrl(), + "error" => $error + ]; } /** @@ -90,4 +119,27 @@ class SettingsController extends Controller { public function formats(){ return $this->config->formats; } + + + /** + * Checking document service location + * + * @param string $documentServer - document service address + * + * @return string + */ + private function сheckDocServiceUrl() { + + $documentService = new DocumentService($this->trans, $this->config); + + try { + $response = $documentService->CommandRequest("version"); + $this->logger->debug("CommandRequest on check: " . $response->error, array("app" => $this->appName)); + } catch (\Exception $e) { + $this->logger->error("CommandRequest on check: " . $e->getMessage(), array("app" => $this->appName)); + return $e->getMessage(); + } + + return ""; + } } diff --git a/js/settings.js b/js/settings.js index 47c8bf1..40312b7 100644 --- a/js/settings.js +++ b/js/settings.js @@ -43,7 +43,12 @@ success: function onSuccess(response) { if (response && response.documentserver != null) { $("#docServiceUrlApi").val(response.documentserver); - var row = OC.Notification.show(t(OCA.Onlyoffice.AppName, "Settings have been successfully updated")); + + var message = + response.error + ? (t(OCA.Onlyoffice.AppName, "Error when trying to connect") + " (" + response.error + ")") + : t(OCA.Onlyoffice.AppName, "Settings have been successfully updated"); + var row = OC.Notification.show(message); setTimeout(function () { OC.Notification.hide(row); }, 3000); diff --git a/lib/documentservice.php b/lib/documentservice.php index e3b0703..4a17727 100644 --- a/lib/documentservice.php +++ b/lib/documentservice.php @@ -22,7 +22,7 @@ * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * -*/ + */ namespace OCA\Onlyoffice; @@ -52,7 +52,8 @@ class DocumentService { private $config; /** - * @param OCA\Onlyoffice\AppConfig $config application configutarion + * @param IL10N $trans - l10n service + * @param OCA\Onlyoffice\AppConfig $config - application configutarion */ public function __construct(IL10N $trans, AppConfig $appConfig) { $this->trans = $trans; @@ -60,12 +61,12 @@ class DocumentService { } /** - * Translation key to a supported form. - * - * @param string $expected_key Expected key - * - * @return Supported key - */ + * Translation key to a supported form. + * + * @param string $expected_key - Expected key + * + * @return string + */ public static function GenerateRevisionId($expected_key) { if (strlen($expected_key) > 20) { $expected_key = crc32( $expected_key); @@ -76,17 +77,17 @@ class DocumentService { } /** - * The method is to convert the file to the required format - * - * @param string $document_uri - Uri for the document to convert - * @param string $from_extension - Document extension - * @param string $to_extension - Extension to which to convert - * @param string $document_revision_id - Key for caching on service - * @param bool $is_async - Perform conversions asynchronously - * @param string $converted_document_uri - Uri to the converted document - * - * @return The percentage of completion of conversion - */ + * The method is to convert the file to the required format and return the percentage of completion + * + * @param string $document_uri - Uri for the document to convert + * @param string $from_extension - Document extension + * @param string $to_extension - Extension to which to convert + * @param string $document_revision_id - Key for caching on service + * @param bool $is_async - Perform conversions asynchronously + * @param string $converted_document_uri - Uri to the converted document + * + * @return int + */ function GetConvertedUri($document_uri, $from_extension, $to_extension, $document_revision_id, $is_async, &$converted_document_uri) { $converted_document_uri = ""; $responceFromConvertService = $this->SendRequestToConvertService($document_uri, $from_extension, $to_extension, $document_revision_id, $is_async); @@ -110,16 +111,16 @@ class DocumentService { } /** - * Request for conversion to a service - * - * @param string $document_uri - Uri for the document to convert - * @param string $from_extension - Document extension - * @param string $to_extension - Extension to which to convert - * @param string $document_revision_id - Key for caching on service - * @param bool - $is_async - Perform conversions asynchronously - * - * @return Xml document request result of conversion - */ + * Request for conversion to a service + * + * @param string $document_uri - Uri for the document to convert + * @param string $from_extension - Document extension + * @param string $to_extension - Extension to which to convert + * @param string $document_revision_id - Key for caching on service + * @param bool - $is_async - Perform conversions asynchronously + * + * @return array + */ function SendRequestToConvertService($document_uri, $from_extension, $to_extension, $document_revision_id, $is_async) { if (empty($from_extension)) { $path_parts = pathinfo($document_uri); @@ -200,12 +201,12 @@ class DocumentService { } /** - * Generate an error code table - * - * @param string $errorCode - Error code - * - * @return null - */ + * Generate an error code table + * + * @param string $errorCode - Error code + * + * @return null + */ function ProcessConvServResponceError($errorCode) { $errorMessageTemplate = $this->trans->t("Error occurred in the document service: "); $errorMessage = ""; @@ -244,4 +245,48 @@ class DocumentService { throw new \Exception($errorMessage); } + + /** + * Send command + * + * @param string $method - type of command + * + * @return array + */ + function CommandRequest($method) { + + $documentServerUrl = $this->config->GetDocumentServerUrl(); + + if (empty($documentServerUrl)) { + throw new \Exception($this->trans->t("ONLYOFFICE app not configured. Please contact admin")); + } + + $urlCommand = $documentServerUrl . "/coauthoring/CommandService.ashx"; + + $data = json_encode( + array( + "c" => $method + ) + ); + + $opts = array("http" => array( + "method" => "POST", + "timeout" => "120000", + "header"=> "Content-type: application/json\r\n", + "content" => $data + ) + ); + + if (substr($urlCommand, 0, strlen("https")) === "https") { + $opts["ssl"] = array( "verify_peer" => FALSE ); + } + + $context = stream_context_create($opts); + + if (($response = file_get_contents($urlCommand, FALSE, $context)) === FALSE){ + throw new \Exception ($this->trans->t("Bad Request or timeout error")); + } + + return json_decode($response); + } } -- cgit v1.2.3 From 013282e8c8af8c15a19c80abb484969d33a82064 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Mon, 3 Apr 2017 15:05:08 +0300 Subject: checking version of onlyoffice (Issue #30) --- controller/settingscontroller.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/controller/settingscontroller.php b/controller/settingscontroller.php index 5e04813..85d993a 100644 --- a/controller/settingscontroller.php +++ b/controller/settingscontroller.php @@ -133,8 +133,14 @@ class SettingsController extends Controller { $documentService = new DocumentService($this->trans, $this->config); try { - $response = $documentService->CommandRequest("version"); - $this->logger->debug("CommandRequest on check: " . $response->error, array("app" => $this->appName)); + $commandResponse = $documentService->CommandRequest("version"); + + $this->logger->debug("CommandRequest on check: " . $commandResponse->error . " version: " . $commandResponse->version, array("app" => $this->appName)); + + $version = floatval($commandResponse->version); + if ($version < 4.2) { + throw new \Exception($this->trans->t("Not supported version")); + } } catch (\Exception $e) { $this->logger->error("CommandRequest on check: " . $e->getMessage(), array("app" => $this->appName)); return $e->getMessage(); -- cgit v1.2.3 From 47489c80298883e1a6da5df807d3641c7879f5d6 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Mon, 3 Apr 2017 16:08:06 +0300 Subject: replace ErrorResponse to JSONResponse --- controller/callbackcontroller.php | 46 ++++++++++++++--------------- lib/errorresponse.php | 61 --------------------------------------- 2 files changed, 23 insertions(+), 84 deletions(-) delete mode 100644 lib/errorresponse.php diff --git a/controller/callbackcontroller.php b/controller/callbackcontroller.php index 4c3e182..0c16300 100644 --- a/controller/callbackcontroller.php +++ b/controller/callbackcontroller.php @@ -22,12 +22,13 @@ * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * -*/ + */ namespace OCA\Onlyoffice\Controller; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\JSONResponse; use OCP\Files\File; use OCP\Files\IRootFolder; use OCP\IL10N; @@ -40,7 +41,6 @@ use OCA\Onlyoffice\AppConfig; use OCA\Onlyoffice\Crypt; use OCA\Onlyoffice\DocumentService; use OCA\Onlyoffice\DownloadResponse; -use OCA\Onlyoffice\ErrorResponse; /** * Callback handler for the document server. @@ -112,15 +112,15 @@ 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 IUserManager $userManager user manager - * @param IL10N $trans l10n service - * @param ILogger $logger logger - * @param OCA\Onlyoffice\AppConfig $config application configuration - * @param OCA\Onlyoffice\Crypt $crypt hash generator + * @param string $AppName - application name + * @param IRequest $request - request object + * @param IRootFolder $root - root folder + * @param IUserSession $userSession - user session + * @param IUserManager $userManager - user manager + * @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, IRequest $request, @@ -161,11 +161,11 @@ class CallbackController extends Controller { $hashData = $this->crypt->ReadHash($doc); if ($hashData === NULL) { $this->logger->info("Download with empty or not correct hash", array("app" => $this->appName)); - return new ErrorResponse(Http::STATUS_FORBIDDEN, $this->trans->t("Access deny")); + return new JSONResponse(["message" => $this->trans->t("Access deny")], Http::STATUS_FORBIDDEN); } if ($hashData->action !== "download") { $this->logger->info("Download with other action", array("app" => $this->appName)); - return new ErrorResponse(Http::STATUS_BAD_REQUEST, $this->trans->t("Invalid request")); + return new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_BAD_REQUEST); } $fileId = $hashData->fileId; @@ -174,22 +174,22 @@ class CallbackController extends Controller { $files = $this->root->getUserFolder($ownerId)->getById($fileId); if (empty($files)) { $this->logger->info("Files for download not found: " . $fileId, array("app" => $this->appName)); - return new ErrorResponse(Http::STATUS_NOT_FOUND, $this->trans->t("Files not found")); + return new JSONResponse(["message" => $this->trans->t("Files not found")], Http::STATUS_NOT_FOUND); } $file = $files[0]; if (! $file instanceof File) { $this->logger->info("File for download not found: " . $fileId, array("app" => $this->appName)); - return new ErrorResponse(Http::STATUS_NOT_FOUND, $this->trans->t("File not found")); + return new JSONResponse(["message" => $this->trans->t("File not found")], Http::STATUS_NOT_FOUND); } try { return new DownloadResponse($file); } catch(\OCP\Files\NotPermittedException $e) { $this->logger->info("Download Not permitted: " . $fileId . " " . $e->getMessage(), array("app" => $this->appName)); - return new ErrorResponse(Http::STATUS_FORBIDDEN, $this->trans->t("Not permitted")); + return new JSONResponse(["message" => $this->trans->t("Not permitted")], Http::STATUS_FORBIDDEN); } - return new ErrorResponse(Http::STATUS_INTERNAL_SERVER_ERROR, $this->trans->t("Download failed")); + return new JSONResponse(["message" => $this->trans->t("Download failed")], Http::STATUS_INTERNAL_SERVER_ERROR); } /** @@ -212,11 +212,11 @@ class CallbackController extends Controller { $hashData = $this->crypt->ReadHash($doc); if ($hashData === NULL) { $this->logger->info("Track with empty or not correct hash", array("app" => $this->appName)); - return ["message" => $this->trans->t("Access deny")]; + return new JSONResponse(["message" => $this->trans->t("Access deny")], Http::STATUS_FORBIDDEN); } if ($hashData->action !== "track") { $this->logger->info("Track with other action", array("app" => $this->appName)); - return ["message" => $this->trans->t("Invalid request")]; + return new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_BAD_REQUEST); } $trackerStatus = $this->_trackerStatus[$status]; @@ -232,13 +232,13 @@ class CallbackController extends Controller { $files = $this->root->getUserFolder($ownerId)->getById($fileId); if (empty($files)) { $this->logger->info("Files for track not found: " . $fileId, array("app" => $this->appName)); - return ["message" => $this->trans->t("Files not found")]; + return new JSONResponse(["message" => $this->trans->t("Files not found")], Http::STATUS_NOT_FOUND); } $file = $files[0]; if (! $file instanceof File) { $this->logger->info("File for track not found: " . $fileId, array("app" => $this->appName)); - return ["message" => $this->trans->t("File not found")]; + return new JSONResponse(["message" => $this->trans->t("File not found")], Http::STATUS_NOT_FOUND); } $fileName = $file->getName(); @@ -255,7 +255,7 @@ class CallbackController extends Controller { $url = $newFileUri; } catch (\Exception $e) { $this->logger->error("GetConvertedUri in track: " . $url . " " . $e->getMessage(), array("app" => $this->appName)); - return ["message" => $e->getMessage()]; + return new JSONResponse(["message" => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR); } } @@ -273,6 +273,6 @@ class CallbackController extends Controller { break; } - return ["error" => $error]; + return new JSONResponse(["error" => $error], ($error === 0 ? Http::STATUS_OK : Http::STATUS_BAD_REQUEST)); } } \ No newline at end of file diff --git a/lib/errorresponse.php b/lib/errorresponse.php deleted file mode 100644 index 512257a..0000000 --- a/lib/errorresponse.php +++ /dev/null @@ -1,61 +0,0 @@ -setStatus($statusCode); - $this->message = $message; - } - - /** - * Returns the rendered file - * - * @return string the file - */ - public function render() { - return $this->message; - } -} \ No newline at end of file -- cgit v1.2.3 From e5a347fc9cfd5b0bcbac673d7c2e63f3c57c3adb Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Mon, 3 Apr 2017 16:13:02 +0300 Subject: replace DownloadResponse to DataDownloadResponse --- controller/callbackcontroller.php | 6 ++-- lib/downloadresponse.php | 64 --------------------------------------- 2 files changed, 3 insertions(+), 67 deletions(-) delete mode 100644 lib/downloadresponse.php diff --git a/controller/callbackcontroller.php b/controller/callbackcontroller.php index 0c16300..f69901f 100644 --- a/controller/callbackcontroller.php +++ b/controller/callbackcontroller.php @@ -28,6 +28,7 @@ namespace OCA\Onlyoffice\Controller; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataDownloadResponse; use OCP\AppFramework\Http\JSONResponse; use OCP\Files\File; use OCP\Files\IRootFolder; @@ -40,7 +41,6 @@ use OCP\IUserSession; use OCA\Onlyoffice\AppConfig; use OCA\Onlyoffice\Crypt; use OCA\Onlyoffice\DocumentService; -use OCA\Onlyoffice\DownloadResponse; /** * Callback handler for the document server. @@ -149,7 +149,7 @@ class CallbackController extends Controller { * * @param string $doc - verification token with the file identifier * - * @return OCA\Onlyoffice\DownloadResponse + * @return DataDownloadResponse * * @NoAdminRequired * @NoCSRFRequired @@ -184,7 +184,7 @@ class CallbackController extends Controller { } try { - return new DownloadResponse($file); + return new DataDownloadResponse($file->getContent(), $file->getName(), $file->getMimeType()); } catch(\OCP\Files\NotPermittedException $e) { $this->logger->info("Download Not permitted: " . $fileId . " " . $e->getMessage(), array("app" => $this->appName)); return new JSONResponse(["message" => $this->trans->t("Not permitted")], Http::STATUS_FORBIDDEN); diff --git a/lib/downloadresponse.php b/lib/downloadresponse.php deleted file mode 100644 index c37bd59..0000000 --- a/lib/downloadresponse.php +++ /dev/null @@ -1,64 +0,0 @@ -setStatus(Http::STATUS_OK); - $this->content = $file->getContent(); - - $this->addHeader("Content-type", $file->getMimeType() . "; charset=utf-8"); - $this->addHeader("Content-Disposition", "attachment; filename*=UTF-8''" . rawurlencode($file->getName()) . "; filename=\"" . rawurlencode($file->getName()) . "\""); - } - - /** - * Returns the rendered file - * - * @return string the file - */ - public function render() { - return $this->content; - } -} -- cgit v1.2.3 From f3e625d2593ff73c9a39c5dfab01ab7ba87ae77b Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Mon, 3 Apr 2017 16:58:06 +0300 Subject: simplify dropping skey --- lib/appconfig.php | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/lib/appconfig.php b/lib/appconfig.php index d58da9e..0af209e 100644 --- a/lib/appconfig.php +++ b/lib/appconfig.php @@ -22,7 +22,7 @@ * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * -*/ + */ namespace OCA\Onlyoffice; @@ -72,7 +72,7 @@ class AppConfig { private $_cryptSecret = "skey"; /** - * @param string $AppName application name + * @param string $AppName - application name */ public function __construct($AppName) { @@ -115,7 +115,7 @@ class AppConfig { */ public function GetSKey() { $skey = $this->config->getAppValue($this->appName, $this->_cryptSecret, ""); - if (empty($skey)) { + if (empty($skey) || $skey === "") { $skey = number_format(round(microtime(true) * 1000), 0, ".", ""); $this->config->setAppValue($this->appName, $this->_cryptSecret, $skey); } @@ -124,15 +124,9 @@ class AppConfig { /** * Regenerate the secret key - * - * @return string */ private function DropSKey() { - $skey = $this->config->getAppValue($this->appName, $this->_cryptSecret, ""); - if (!empty($skey)) { - $skey = number_format(round(microtime(true) * 1000), 0, ".", ""); - $this->config->setAppValue($this->appName, $this->_cryptSecret, $skey); - } + $this->config->setAppValue($this->appName, $this->_cryptSecret, ""); } -- cgit v1.2.3 From d7c0e65ec7aa436f92b5d567ff0ab13ea42e91b7 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Mon, 3 Apr 2017 17:23:09 +0300 Subject: possibility preset Document Server url --- lib/appconfig.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/appconfig.php b/lib/appconfig.php index 0af209e..a9b42f9 100644 --- a/lib/appconfig.php +++ b/lib/appconfig.php @@ -36,6 +36,14 @@ use OCP\ILogger; */ class AppConfig { + /** + * Definition url on server + * + * @var string + */ + private $predefDocumentServerUrl = ""; + + /** * Application name * @@ -105,7 +113,11 @@ class AppConfig { * @return string */ public function GetDocumentServerUrl() { - return $this->config->getAppValue($this->appName, $this->_documentserver, ""); + $url = $this->config->getAppValue($this->appName, $this->_documentserver, ""); + if (empty($url) || $url === "") { + $url = $this->predefDocumentServerUrl; + } + return $url; } /** -- cgit v1.2.3 From 091c732163d6325e4ad45edebc0039b6c8a253d9 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Mon, 3 Apr 2017 17:25:27 +0300 Subject: ajax request editor config --- appinfo/routes.php | 3 +- controller/editorcontroller.php | 70 +++++++++++++++++++++++------------------ js/editor.js | 55 ++++++++++++++++---------------- templates/editor.php | 14 ++------- 4 files changed, 71 insertions(+), 71 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index cfd973a..e81b5d8 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -22,13 +22,14 @@ * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * -*/ + */ return [ "routes" => [ ["name" => "callback#download", "url" => "/download", "verb" => "GET"], ["name" => "callback#track", "url" => "/track", "verb" => "POST"], ["name" => "editor#index", "url" => "/{fileId}", "verb" => "GET"], + ["name" => "editor#config", "url" => "/ajax/config/{fileId}", "verb" => "GET"], ["name" => "editor#create", "url" => "/ajax/new", "verb" => "POST"], ["name" => "editor#convert", "url" => "/ajax/convert", "verb" => "POST"], ["name" => "settings#settings", "url" => "/ajax/settings", "verb" => "PUT"], diff --git a/controller/editorcontroller.php b/controller/editorcontroller.php index 0f48326..a5d418e 100644 --- a/controller/editorcontroller.php +++ b/controller/editorcontroller.php @@ -22,7 +22,7 @@ * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * -*/ + */ namespace OCA\Onlyoffice\Controller; @@ -105,15 +105,15 @@ class EditorController extends Controller { private $crypt; /** - * @param string $AppName application name - * @param IRequest $request request object - * @param IRootFolder $root root folder - * @param IUserSession $userSession current user session - * @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 + * @param string $AppName - application name + * @param IRequest $request - request object + * @param IRootFolder $root - root folder + * @param IUserSession $userSession - current user session + * @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, IRequest $request, @@ -252,7 +252,7 @@ class EditorController extends Controller { $newFileName = $folder->getNonExistingName($fileNameWithoutExt . "." . $internalExtension); $newFilePath = $newFolderPath . DIRECTORY_SEPARATOR . $newFileName; - + if (($newData = file_get_contents($newFileUri)) === FALSE){ $this->logger->error("Failed download converted file: " . $newFileUri, array("app" => $this->appName)); return ["error" => $this->trans->t("Failed download converted file")]; @@ -286,14 +286,23 @@ class EditorController extends Controller { * @NoCSRFRequired */ public function index($fileId) { - $params = $this->getParam($fileId); + $documentServerUrl = $this->config->GetDocumentServerUrl(); + + if (empty($documentServerUrl)) { + $this->logger->error("documentServerUrl is empty", array("app" => $this->appName)); + return ["error" => $this->trans->t("ONLYOFFICE app not configured. Please contact admin")]; + } + + $params = [ + "documentServerUrl" => $documentServerUrl, + "fileId" => $fileId + ]; $response = new TemplateResponse($this->appName, "editor", $params); $csp = new ContentSecurityPolicy(); $csp->allowInlineScript(true); - $documentServerUrl = $params["documentServerUrl"]; if (isset($documentServerUrl) && !empty($documentServerUrl)) { $csp->addAllowedScriptDomain($documentServerUrl); $csp->addAllowedFrameDomain($documentServerUrl); @@ -309,8 +318,10 @@ class EditorController extends Controller { * @param integer $fileId - file identifier * * @return array + * + * @NoAdminRequired */ - private function getParam($fileId) { + public function config($fileId) { list ($file, $error) = $this->getFile($fileId); if (isset($error)) { @@ -326,13 +337,6 @@ class EditorController extends Controller { return ["error" => $this->trans->t("Format do not supported")]; } - $documentServerUrl = $this->config->GetDocumentServerUrl(); - - if (empty($documentServerUrl)) { - $this->logger->error("documentServerUrl is empty", array("app" => $this->appName)); - return ["error" => $this->trans->t("ONLYOFFICE app not configured. Please contact admin")]; - } - $userId = $this->userSession->getUser()->getUID(); $ownerId = $file->getOwner()->getUID(); try { @@ -347,17 +351,23 @@ class EditorController extends Controller { $key = $this->getKey($file); $canEdit = isset($format["edit"]) && $format["edit"]; + $callback = ($file->isUpdateable() && $canEdit ? $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.track", ["doc" => $hashCallback]) : NULL); $params = [ - "documentServerUrl" => $documentServerUrl, - - "callback" => ($file->isUpdateable() && $canEdit ? $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.track", ["doc" => $hashCallback]) : NULL), - "fileName" => $fileName, - "key" => DocumentService::GenerateRevisionId($key), - "url" => $fileUrl, - "userId" => $userId, - "userName" => $this->userSession->getUser()->getDisplayName(), - "documentType" => $format["type"] + "document" => [ + "key" => DocumentService::GenerateRevisionId($key), + "title" => $fileName, + "url" => $fileUrl, + ], + "documentType" => $format["type"], + "editorConfig" => [ + "callbackUrl" => $callback, + "mode" => ($callback === NULL ? "view" : "edit"), + "user" => [ + "id" => $userId, + "name" => $this->userSession->getUser()->getDisplayName() + ] + ] ]; return $params; diff --git a/js/editor.js b/js/editor.js index 2a7851d..949744a 100644 --- a/js/editor.js +++ b/js/editor.js @@ -32,41 +32,40 @@ }; } - OCA.Onlyoffice.OpenEditor = function (data) { - if (typeof DocsAPI === "undefined" && !data.error.length) { - data.error = t(OCA.Onlyoffice.AppName, "ONLYOFFICE app not configured. Please contact admin"); + OCA.Onlyoffice.OpenEditor = function (fileId, error) { + + var displayError = function (error) { + $("#iframeEditor").text(error).addClass("error"); + }; + + if (error.length) { + displayError(error) + return; } - if (data.error.length) { - $("#iframeEditor").text(data.error).addClass("error"); + if (!fileId.length) { + displayError(t(OCA.Onlyoffice.AppName, "FileId is empty")); return; } - var ext = (data.title || "").toLowerCase().split(".").pop(); + if (typeof DocsAPI === "undefined" && !error.length) { + displayError(t(OCA.Onlyoffice.AppName, "ONLYOFFICE not reached. Please contact admin")); + return; + } - var config = { - "document": { - "fileType": ext, - "key": data.key, - "title": data.title, - "url": data.url - }, - "documentType": data.documentType, - "editorConfig": { - "callbackUrl": (data.callbackUrl ? data.callbackUrl : null), - "lang": "en-US", - "mode": (data.callbackUrl ? "edit" : "view"), - "user": { - "id": data.userId, - "name": data.userName - } - }, - "height": "100%", - "type": "desktop", - "width": "100%" - }; + $.ajax({ + url: OC.generateUrl("apps/onlyoffice/ajax/config/" + fileId), + success: function onSuccess(config) { + if (config) { + if (config.error != null) { + displayError(config.error); + return; + } - var docEditor = new DocsAPI.DocEditor("iframeEditor", config); + var docEditor = new DocsAPI.DocEditor("iframeEditor", config); + } + } + }); }; })(jQuery, OCA); \ No newline at end of file diff --git a/templates/editor.php b/templates/editor.php index 371cf55..724f745 100644 --- a/templates/editor.php +++ b/templates/editor.php @@ -22,7 +22,7 @@ * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * -*/ + */ style("onlyoffice", "editor"); script("onlyoffice", "editor"); @@ -39,17 +39,7 @@ } ?> -- cgit v1.2.3 From ad6d2f62b3d59d38733219b8921acad659c6f9db Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Tue, 4 Apr 2017 12:47:00 +0300 Subject: editor language as user language --- controller/editorcontroller.php | 1 + 1 file changed, 1 insertion(+) diff --git a/controller/editorcontroller.php b/controller/editorcontroller.php index a5d418e..92be023 100644 --- a/controller/editorcontroller.php +++ b/controller/editorcontroller.php @@ -362,6 +362,7 @@ class EditorController extends Controller { "documentType" => $format["type"], "editorConfig" => [ "callbackUrl" => $callback, + "lang" => \OC::$server->getL10NFactory()->get()->getLanguageCode(), "mode" => ($callback === NULL ? "view" : "edit"), "user" => [ "id" => $userId, -- cgit v1.2.3 From 5b6d9c0d033eacbc53382fdaef2deb7f66938d6e Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Tue, 4 Apr 2017 14:58:21 +0300 Subject: Set secret key on admin page --- controller/settingscontroller.php | 9 +++++++-- css/settings.css | 3 +++ js/settings.js | 20 +++++++++++++++----- lib/adminsettings.php | 2 +- lib/appconfig.php | 31 +++++++++++++++++++++++++++++++ templates/settings.php | 9 +++++++-- 6 files changed, 64 insertions(+), 10 deletions(-) diff --git a/controller/settingscontroller.php b/controller/settingscontroller.php index 85d993a..3496ac8 100644 --- a/controller/settingscontroller.php +++ b/controller/settingscontroller.php @@ -87,7 +87,10 @@ class SettingsController extends Controller { * @return TemplateResponse */ public function index() { - $data = ["documentserver" => $this->config->GetDocumentServerUrl()]; + $data = [ + "documentserver" => $this->config->GetDocumentServerUrl(), + "secret" => $this->config->GetDocumentServerSecret() + ]; return new TemplateResponse($this->appName, "settings", $data, "blank"); } @@ -95,11 +98,13 @@ class SettingsController extends Controller { * Save the document server address * * @param string $documentserver - document service address + * @param string $secret - secret key for signature * * @return array */ - public function settings($documentserver) { + public function settings($documentserver, $secret) { $this->config->SetDocumentServerUrl($documentserver); + $this->config->SetDocumentServerSecret($secret); $error = $this->сheckDocServiceUrl(); diff --git a/css/settings.css b/css/settings.css index 8c45562..4be07de 100644 --- a/css/settings.css +++ b/css/settings.css @@ -34,3 +34,6 @@ margin: 6px 0 4px; width: 250px; } +.onlyoffice-hide { + display: none; +} diff --git a/js/settings.js b/js/settings.js index 40312b7..69c4174 100644 --- a/js/settings.js +++ b/js/settings.js @@ -34,15 +34,25 @@ } $("#onlyofficeSave").click(function () { - var docServiceUrlApi = $("#docServiceUrlApi").val().trim(); + var onlyofficeUrl = $("#onlyofficeUrl").val().trim(); + + if (!onlyofficeUrl.length) { + $("#onlyofficeSecret").val(""); + } + var onlyofficeSecret = $("#onlyofficeSecret").val(); $.ajax({ method: "PUT", url: OC.generateUrl("apps/onlyoffice/ajax/settings"), - data: { documentserver: docServiceUrlApi }, + data: { + documentserver: onlyofficeUrl, + secret: onlyofficeSecret + }, success: function onSuccess(response) { if (response && response.documentserver != null) { - $("#docServiceUrlApi").val(response.documentserver); + $("#onlyofficeUrl").val(response.documentserver); + + $("#onlyofficeSecretPanel").toggleClass("onlyoffice-hide", !response.documentserver.length); var message = response.error @@ -57,7 +67,7 @@ }); }); - $("#docServiceUrlApi").keypress(function (e) { + $("#onlyofficeUrl, #onlyofficeSecret").keypress(function (e) { var code = e.keyCode || e.which; if (code === 13) { $("#onlyofficeSave").click(); @@ -65,4 +75,4 @@ }); }); -})(jQuery, OC); \ No newline at end of file +})(jQuery, OC); diff --git a/lib/adminsettings.php b/lib/adminsettings.php index 7497e75..11c0f55 100644 --- a/lib/adminsettings.php +++ b/lib/adminsettings.php @@ -22,7 +22,7 @@ * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * -*/ + */ namespace OCA\Onlyoffice; diff --git a/lib/appconfig.php b/lib/appconfig.php index a9b42f9..72f811e 100644 --- a/lib/appconfig.php +++ b/lib/appconfig.php @@ -72,6 +72,13 @@ class AppConfig { */ private $_documentserver = "DocumentServerUrl"; + /** + * The config key for the secret key in jwt + * + * @var string + */ + private $_secret = "DocumentServerSecret"; + /** * The config key for the secret key * @@ -120,6 +127,30 @@ class AppConfig { return $url; } + /** + * Save the document service secret key to the application configuration + * + * @param string $secret - secret key + */ + public function SetDocumentServerSecret($secret) { + if (empty($secret)) { + $this->logger->info("Clear secret key", array("app" => $this->appName)); + } else { + $this->logger->info("Set secret key", array("app" => $this->appName)); + } + + $this->config->setAppValue($this->appName, $this->_secret, $secret); + } + + /** + * Get the document service secret key from the application configuration + * + * @return string + */ + public function GetDocumentServerSecret() { + return $this->config->getAppValue($this->appName, $this->_secret, ""); + } + /** * Get the secret key from the application configuration * diff --git a/templates/settings.php b/templates/settings.php index b721ba4..c34368c 100644 --- a/templates/settings.php +++ b/templates/settings.php @@ -22,7 +22,7 @@ * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * -*/ + */ style("onlyoffice", "settings"); script("onlyoffice", "settings"); @@ -34,7 +34,12 @@

t("ONLYOFFICE Document Service Location specifies the address of the server with the document services installed. Please change the '' for the server address in the below line.")) ?>

t("Document Editing Service Address")) ?>

- " placeholder="https://" type="text"> + " placeholder="https://" type="text"> + +
"> +

t("Secret key (leave blank to disable)")) ?>

+ " placeholder="secret" type="text"> +

t("Save")) ?> -- cgit v1.2.3 From 49a9478a387f9039d9bbeed9983a40d456036c9a Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Tue, 4 Apr 2017 15:19:34 +0300 Subject: jwt for config --- 3rdparty/jwt/BeforeValidException.php | 7 + 3rdparty/jwt/ExpiredException.php | 7 + 3rdparty/jwt/JWT.php | 370 +++++++++++++++++++++++++++++ 3rdparty/jwt/LICENSE | 30 +++ 3rdparty/jwt/SignatureInvalidException.php | 7 + appinfo/application.php | 2 + controller/editorcontroller.php | 5 + 7 files changed, 428 insertions(+) create mode 100644 3rdparty/jwt/BeforeValidException.php create mode 100644 3rdparty/jwt/ExpiredException.php create mode 100644 3rdparty/jwt/JWT.php create mode 100644 3rdparty/jwt/LICENSE create mode 100644 3rdparty/jwt/SignatureInvalidException.php diff --git a/3rdparty/jwt/BeforeValidException.php b/3rdparty/jwt/BeforeValidException.php new file mode 100644 index 0000000..a6ee2f7 --- /dev/null +++ b/3rdparty/jwt/BeforeValidException.php @@ -0,0 +1,7 @@ + + * @author Anant Narayanan + * @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD + * @link https://github.com/firebase/php-jwt + */ +class JWT +{ + + /** + * When checking nbf, iat or expiration times, + * we want to provide some extra leeway time to + * account for clock skew. + */ + public static $leeway = 0; + + /** + * Allow the current timestamp to be specified. + * Useful for fixing a value within unit testing. + * + * Will default to PHP time() value if null. + */ + public static $timestamp = null; + + public static $supported_algs = array( + 'HS256' => array('hash_hmac', 'SHA256'), + 'HS512' => array('hash_hmac', 'SHA512'), + 'HS384' => array('hash_hmac', 'SHA384'), + 'RS256' => array('openssl', 'SHA256'), + ); + + /** + * Decodes a JWT string into a PHP object. + * + * @param string $jwt The JWT + * @param string|array $key The key, or map of keys. + * If the algorithm used is asymmetric, this is the public key + * @param array $allowed_algs List of supported verification algorithms + * Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256' + * + * @return object The JWT's payload as a PHP object + * + * @throws UnexpectedValueException Provided JWT was invalid + * @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed + * @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf' + * @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat' + * @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim + * + * @uses jsonDecode + * @uses urlsafeB64Decode + */ + public static function decode($jwt, $key, $allowed_algs = array()) + { + $timestamp = is_null(static::$timestamp) ? time() : static::$timestamp; + + if (empty($key)) { + throw new InvalidArgumentException('Key may not be empty'); + } + if (!is_array($allowed_algs)) { + throw new InvalidArgumentException('Algorithm not allowed'); + } + $tks = explode('.', $jwt); + if (count($tks) != 3) { + throw new UnexpectedValueException('Wrong number of segments'); + } + list($headb64, $bodyb64, $cryptob64) = $tks; + if (null === ($header = static::jsonDecode(static::urlsafeB64Decode($headb64)))) { + throw new UnexpectedValueException('Invalid header encoding'); + } + if (null === $payload = static::jsonDecode(static::urlsafeB64Decode($bodyb64))) { + throw new UnexpectedValueException('Invalid claims encoding'); + } + $sig = static::urlsafeB64Decode($cryptob64); + + if (empty($header->alg)) { + throw new UnexpectedValueException('Empty algorithm'); + } + if (empty(static::$supported_algs[$header->alg])) { + throw new UnexpectedValueException('Algorithm not supported'); + } + if (!in_array($header->alg, $allowed_algs)) { + throw new UnexpectedValueException('Algorithm not allowed'); + } + if (is_array($key) || $key instanceof \ArrayAccess) { + if (isset($header->kid)) { + $key = $key[$header->kid]; + } else { + throw new UnexpectedValueException('"kid" empty, unable to lookup correct key'); + } + } + + // Check the signature + if (!static::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) { + throw new SignatureInvalidException('Signature verification failed'); + } + + // Check if the nbf if it is defined. This is the time that the + // token can actually be used. If it's not yet that time, abort. + if (isset($payload->nbf) && $payload->nbf > ($timestamp + static::$leeway)) { + throw new BeforeValidException( + 'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->nbf) + ); + } + + // Check that this token has been created before 'now'. This prevents + // using tokens that have been created for later use (and haven't + // correctly used the nbf claim). + if (isset($payload->iat) && $payload->iat > ($timestamp + static::$leeway)) { + throw new BeforeValidException( + 'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat) + ); + } + + // Check if this token has expired. + if (isset($payload->exp) && ($timestamp - static::$leeway) >= $payload->exp) { + throw new ExpiredException('Expired token'); + } + + return $payload; + } + + /** + * Converts and signs a PHP object or array into a JWT string. + * + * @param object|array $payload PHP object or array + * @param string $key The secret key. + * If the algorithm used is asymmetric, this is the private key + * @param string $alg The signing algorithm. + * Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256' + * @param mixed $keyId + * @param array $head An array with header elements to attach + * + * @return string A signed JWT + * + * @uses jsonEncode + * @uses urlsafeB64Encode + */ + public static function encode($payload, $key, $alg = 'HS256', $keyId = null, $head = null) + { + $header = array('typ' => 'JWT', 'alg' => $alg); + if ($keyId !== null) { + $header['kid'] = $keyId; + } + if ( isset($head) && is_array($head) ) { + $header = array_merge($head, $header); + } + $segments = array(); + $segments[] = static::urlsafeB64Encode(static::jsonEncode($header)); + $segments[] = static::urlsafeB64Encode(static::jsonEncode($payload)); + $signing_input = implode('.', $segments); + + $signature = static::sign($signing_input, $key, $alg); + $segments[] = static::urlsafeB64Encode($signature); + + return implode('.', $segments); + } + + /** + * Sign a string with a given key and algorithm. + * + * @param string $msg The message to sign + * @param string|resource $key The secret key + * @param string $alg The signing algorithm. + * Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256' + * + * @return string An encrypted message + * + * @throws DomainException Unsupported algorithm was specified + */ + public static function sign($msg, $key, $alg = 'HS256') + { + if (empty(static::$supported_algs[$alg])) { + throw new DomainException('Algorithm not supported'); + } + list($function, $algorithm) = static::$supported_algs[$alg]; + switch($function) { + case 'hash_hmac': + return hash_hmac($algorithm, $msg, $key, true); + case 'openssl': + $signature = ''; + $success = openssl_sign($msg, $signature, $key, $algorithm); + if (!$success) { + throw new DomainException("OpenSSL unable to sign data"); + } else { + return $signature; + } + } + } + + /** + * Verify a signature with the message, key and method. Not all methods + * are symmetric, so we must have a separate verify and sign method. + * + * @param string $msg The original message (header and body) + * @param string $signature The original signature + * @param string|resource $key For HS*, a string key works. for RS*, must be a resource of an openssl public key + * @param string $alg The algorithm + * + * @return bool + * + * @throws DomainException Invalid Algorithm or OpenSSL failure + */ + private static function verify($msg, $signature, $key, $alg) + { + if (empty(static::$supported_algs[$alg])) { + throw new DomainException('Algorithm not supported'); + } + + list($function, $algorithm) = static::$supported_algs[$alg]; + switch($function) { + case 'openssl': + $success = openssl_verify($msg, $signature, $key, $algorithm); + if (!$success) { + throw new DomainException("OpenSSL unable to verify data: " . openssl_error_string()); + } else { + return $signature; + } + case 'hash_hmac': + default: + $hash = hash_hmac($algorithm, $msg, $key, true); + if (function_exists('hash_equals')) { + return hash_equals($signature, $hash); + } + $len = min(static::safeStrlen($signature), static::safeStrlen($hash)); + + $status = 0; + for ($i = 0; $i < $len; $i++) { + $status |= (ord($signature[$i]) ^ ord($hash[$i])); + } + $status |= (static::safeStrlen($signature) ^ static::safeStrlen($hash)); + + return ($status === 0); + } + } + + /** + * Decode a JSON string into a PHP object. + * + * @param string $input JSON string + * + * @return object Object representation of JSON string + * + * @throws DomainException Provided string was invalid JSON + */ + public static function jsonDecode($input) + { + if (version_compare(PHP_VERSION, '5.4.0', '>=') && !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) { + /** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you + * to specify that large ints (like Steam Transaction IDs) should be treated as + * strings, rather than the PHP default behaviour of converting them to floats. + */ + $obj = json_decode($input, false, 512, JSON_BIGINT_AS_STRING); + } else { + /** Not all servers will support that, however, so for older versions we must + * manually detect large ints in the JSON string and quote them (thus converting + *them to strings) before decoding, hence the preg_replace() call. + */ + $max_int_length = strlen((string) PHP_INT_MAX) - 1; + $json_without_bigints = preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input); + $obj = json_decode($json_without_bigints); + } + + if (function_exists('json_last_error') && $errno = json_last_error()) { + static::handleJsonError($errno); + } elseif ($obj === null && $input !== 'null') { + throw new DomainException('Null result with non-null input'); + } + return $obj; + } + + /** + * Encode a PHP object into a JSON string. + * + * @param object|array $input A PHP object or array + * + * @return string JSON representation of the PHP object or array + * + * @throws DomainException Provided object could not be encoded to valid JSON + */ + public static function jsonEncode($input) + { + $json = json_encode($input); + if (function_exists('json_last_error') && $errno = json_last_error()) { + static::handleJsonError($errno); + } elseif ($json === 'null' && $input !== null) { + throw new DomainException('Null result with non-null input'); + } + return $json; + } + + /** + * Decode a string with URL-safe Base64. + * + * @param string $input A Base64 encoded string + * + * @return string A decoded string + */ + public static function urlsafeB64Decode($input) + { + $remainder = strlen($input) % 4; + if ($remainder) { + $padlen = 4 - $remainder; + $input .= str_repeat('=', $padlen); + } + return base64_decode(strtr($input, '-_', '+/')); + } + + /** + * Encode a string with URL-safe Base64. + * + * @param string $input The string you want encoded + * + * @return string The base64 encode of what you passed in + */ + public static function urlsafeB64Encode($input) + { + return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); + } + + /** + * Helper method to create a JSON error. + * + * @param int $errno An error number from json_last_error() + * + * @return void + */ + private static function handleJsonError($errno) + { + $messages = array( + JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', + JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', + JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON' + ); + throw new DomainException( + isset($messages[$errno]) + ? $messages[$errno] + : 'Unknown JSON error: ' . $errno + ); + } + + /** + * Get the number of bytes in cryptographic strings. + * + * @param string + * + * @return int + */ + private static function safeStrlen($str) + { + if (function_exists('mb_strlen')) { + return mb_strlen($str, '8bit'); + } + return strlen($str); + } +} diff --git a/3rdparty/jwt/LICENSE b/3rdparty/jwt/LICENSE new file mode 100644 index 0000000..cb0c49b --- /dev/null +++ b/3rdparty/jwt/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2011, Neuman Vong + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Neuman Vong nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/3rdparty/jwt/SignatureInvalidException.php b/3rdparty/jwt/SignatureInvalidException.php new file mode 100644 index 0000000..27332b2 --- /dev/null +++ b/3rdparty/jwt/SignatureInvalidException.php @@ -0,0 +1,7 @@ +getContainer(); diff --git a/controller/editorcontroller.php b/controller/editorcontroller.php index 92be023..c561cb3 100644 --- a/controller/editorcontroller.php +++ b/controller/editorcontroller.php @@ -371,6 +371,11 @@ class EditorController extends Controller { ] ]; + if (!empty($this->config->GetDocumentServerSecret())) { + $token = \Firebase\JWT\JWT::encode($params, $this->config->GetDocumentServerSecret()); + $params->token = $token; + } + return $params; } -- cgit v1.2.3 From 7f08626dfb7bc0fc96888332aca06e312ab4ed03 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Tue, 4 Apr 2017 16:21:05 +0300 Subject: parsing error on command request --- controller/settingscontroller.php | 8 +++--- lib/documentservice.php | 54 +++++++++++++++++++++++++++++++++------ 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/controller/settingscontroller.php b/controller/settingscontroller.php index 3496ac8..7caf814 100644 --- a/controller/settingscontroller.php +++ b/controller/settingscontroller.php @@ -106,7 +106,7 @@ class SettingsController extends Controller { $this->config->SetDocumentServerUrl($documentserver); $this->config->SetDocumentServerSecret($secret); - $error = $this->сheckDocServiceUrl(); + $error = $this->checkDocServiceUrl(); return [ "documentserver" => $this->config->GetDocumentServerUrl(), @@ -133,21 +133,21 @@ class SettingsController extends Controller { * * @return string */ - private function сheckDocServiceUrl() { + private function checkDocServiceUrl() { $documentService = new DocumentService($this->trans, $this->config); try { $commandResponse = $documentService->CommandRequest("version"); - $this->logger->debug("CommandRequest on check: " . $commandResponse->error . " version: " . $commandResponse->version, array("app" => $this->appName)); + $this->logger->debug("CommandRequest on check: " . json_encode($commandResponse), array("app" => $this->appName)); $version = floatval($commandResponse->version); if ($version < 4.2) { throw new \Exception($this->trans->t("Not supported version")); } } catch (\Exception $e) { - $this->logger->error("CommandRequest on check: " . $e->getMessage(), array("app" => $this->appName)); + $this->logger->error("CommandRequest on check error: " . $e->getMessage(), array("app" => $this->appName)); return $e->getMessage(); } diff --git a/lib/documentservice.php b/lib/documentservice.php index 4a17727..35d482f 100644 --- a/lib/documentservice.php +++ b/lib/documentservice.php @@ -201,7 +201,7 @@ class DocumentService { } /** - * Generate an error code table + * Generate an error code table of convertion * * @param string $errorCode - Error code * @@ -212,29 +212,32 @@ class DocumentService { $errorMessage = ""; switch ($errorCode) { + case -20: + $errorMessage = $errorMessageTemplate . "Error encrypt signature"; + break; case -8: - $errorMessage = $errorMessageTemplate . "Error document VKey"; + $errorMessage = $errorMessageTemplate . "Invalid token"; break; case -7: $errorMessage = $errorMessageTemplate . "Error document request"; break; case -6: - $errorMessage = $errorMessageTemplate . "Error database"; + $errorMessage = $errorMessageTemplate . "Error while accessing the conversion result database"; break; case -5: $errorMessage = $errorMessageTemplate . "Error unexpected guid"; break; case -4: - $errorMessage = $errorMessageTemplate . "Error download error"; + $errorMessage = $errorMessageTemplate . "Error while downloading the document file to be converted."; break; case -3: - $errorMessage = $errorMessageTemplate . "Error convertation error"; + $errorMessage = $errorMessageTemplate . "Conversion error"; break; case -2: - $errorMessage = $errorMessageTemplate . "Error convertation timeout"; + $errorMessage = $errorMessageTemplate . "Timeout conversion error"; break; case -1: - $errorMessage = $errorMessageTemplate . "Error convertation unknown"; + $errorMessage = $errorMessageTemplate . "Unknown error"; break; case 0: break; @@ -287,6 +290,41 @@ class DocumentService { throw new \Exception ($this->trans->t("Bad Request or timeout error")); } - return json_decode($response); + $data = json_decode($response); + + $this->ProcessCommandServResponceError($data->error); + + return $data; + } + + /** + * Generate an error code table of command + * + * @param string $errorCode - Error code + * + * @return null + */ + function ProcessCommandServResponceError($errorCode) { + $errorMessageTemplate = $this->trans->t("Error occurred in the document service: "); + $errorMessage = ""; + + switch ($errorCode) { + case 6: + $errorMessage = $errorMessageTemplate . "Invalid token"; + break; + case 5: + $errorMessage = $errorMessageTemplate . "Command not correсt"; + break; + case 3: + $errorMessage = $errorMessageTemplate . "Internal server error"; + break; + case 0: + return; + default: + $errorMessage = $errorMessageTemplate . "ErrorCode = " . $errorCode; + break; + } + + throw new \Exception($errorMessage); } } -- cgit v1.2.3 From e793724b3db20ce669f06e717421c3e5c0015789 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Tue, 4 Apr 2017 16:33:11 +0300 Subject: jwt for request to document server --- appinfo/app.php | 2 +- appinfo/application.php | 4 ++-- lib/documentservice.php | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/appinfo/app.php b/appinfo/app.php index 469955d..68ebda6 100644 --- a/appinfo/app.php +++ b/appinfo/app.php @@ -22,7 +22,7 @@ * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * -*/ + */ namespace OCA\Onlyoffice\AppInfo; diff --git a/appinfo/application.php b/appinfo/application.php index c8faedc..23e2fd0 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -71,10 +71,10 @@ class Application extends App { Util::addStyle($appName, "main"); } } - - require_once __DIR__ . "/../3rdparty/jwt/JWT.php"; } + require_once __DIR__ . "/../3rdparty/jwt/JWT.php"; + $container = $this->getContainer(); $container->registerService("L10N", function($c) { diff --git a/lib/documentservice.php b/lib/documentservice.php index 35d482f..a0c0140 100644 --- a/lib/documentservice.php +++ b/lib/documentservice.php @@ -168,6 +168,14 @@ class DocumentService { ) ); + if (!empty($this->config->GetDocumentServerSecret())) { + $params = [ + "payload" => $data + ]; + $token = \Firebase\JWT\JWT::encode($params, $this->config->GetDocumentServerSecret()); + $opts["http"]["header"] = $opts["http"]["header"] . "Authorization: Bearer " . $token . "\r\n"; + } + if (substr($urlToConverter, 0, strlen("https")) === "https") { $opts["ssl"] = array( "verify_peer" => FALSE ); } @@ -280,6 +288,14 @@ class DocumentService { ) ); + if (!empty($this->config->GetDocumentServerSecret())) { + $params = [ + "payload" => $data + ]; + $token = \Firebase\JWT\JWT::encode($params, $this->config->GetDocumentServerSecret()); + $opts["http"]["header"] = $opts["http"]["header"] . "Authorization: Bearer " . $token . "\r\n"; + } + if (substr($urlCommand, 0, strlen("https")) === "https") { $opts["ssl"] = array( "verify_peer" => FALSE ); } -- cgit v1.2.3 From e64d1fb0eb07bd2bfeaa29d9323134e29858afe6 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Tue, 4 Apr 2017 17:32:16 +0300 Subject: possibility preset secret --- lib/appconfig.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/appconfig.php b/lib/appconfig.php index 72f811e..508de9b 100644 --- a/lib/appconfig.php +++ b/lib/appconfig.php @@ -43,6 +43,13 @@ class AppConfig { */ private $predefDocumentServerUrl = ""; + /** + * Definition url on server + * + * @var string + */ + private $predefDocumentServerSecret = ""; + /** * Application name @@ -148,7 +155,11 @@ class AppConfig { * @return string */ public function GetDocumentServerSecret() { - return $this->config->getAppValue($this->appName, $this->_secret, ""); + $secret = $this->config->getAppValue($this->appName, $this->_secret, ""); + if (empty($secret) || $secret == "") { + $secret = $this->predefDocumentServerSecret; + } + return $secret; } /** -- cgit v1.2.3 From 56a03d56aeedb922f6f8cf9bbc2a788b2111c8e2 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Wed, 5 Apr 2017 16:35:54 +0300 Subject: checking document server if address is not empty --- controller/settingscontroller.php | 5 ++++- lib/appconfig.php | 6 +++--- lib/crypt.php | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/controller/settingscontroller.php b/controller/settingscontroller.php index 7caf814..33290b8 100644 --- a/controller/settingscontroller.php +++ b/controller/settingscontroller.php @@ -106,7 +106,10 @@ class SettingsController extends Controller { $this->config->SetDocumentServerUrl($documentserver); $this->config->SetDocumentServerSecret($secret); - $error = $this->checkDocServiceUrl(); + $documentserver = $this->config->GetDocumentServerUrl(); + if (!empty($documentserver)) { + $error = $this->checkDocServiceUrl(); + } return [ "documentserver" => $this->config->GetDocumentServerUrl(), diff --git a/lib/appconfig.php b/lib/appconfig.php index 508de9b..3cf78be 100644 --- a/lib/appconfig.php +++ b/lib/appconfig.php @@ -128,7 +128,7 @@ class AppConfig { */ public function GetDocumentServerUrl() { $url = $this->config->getAppValue($this->appName, $this->_documentserver, ""); - if (empty($url) || $url === "") { + if (empty($url)) { $url = $this->predefDocumentServerUrl; } return $url; @@ -156,7 +156,7 @@ class AppConfig { */ public function GetDocumentServerSecret() { $secret = $this->config->getAppValue($this->appName, $this->_secret, ""); - if (empty($secret) || $secret == "") { + if (empty($secret)) { $secret = $this->predefDocumentServerSecret; } return $secret; @@ -169,7 +169,7 @@ class AppConfig { */ public function GetSKey() { $skey = $this->config->getAppValue($this->appName, $this->_cryptSecret, ""); - if (empty($skey) || $skey === "") { + if (empty($skey)) { $skey = number_format(round(microtime(true) * 1000), 0, ".", ""); $this->config->setAppValue($this->appName, $this->_cryptSecret, $skey); } diff --git a/lib/crypt.php b/lib/crypt.php index 28c888b..14222d2 100644 --- a/lib/crypt.php +++ b/lib/crypt.php @@ -22,7 +22,7 @@ * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * -*/ + */ namespace OCA\Onlyoffice; @@ -43,7 +43,7 @@ class Crypt { private $skey; /** - * @param OCA\Onlyoffice\AppConfig $config application configutarion + * @param OCA\Onlyoffice\AppConfig $config - application configutarion */ public function __construct(AppConfig $appConfig) { $this->skey = $appConfig->GetSKey(); -- cgit v1.2.3 From 100654440837ee1d2fd815f2411941e8ab91e81a Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Wed, 5 Apr 2017 17:45:07 +0300 Subject: l10n argument --- controller/editorcontroller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/editorcontroller.php b/controller/editorcontroller.php index c561cb3..08ed638 100644 --- a/controller/editorcontroller.php +++ b/controller/editorcontroller.php @@ -362,7 +362,7 @@ class EditorController extends Controller { "documentType" => $format["type"], "editorConfig" => [ "callbackUrl" => $callback, - "lang" => \OC::$server->getL10NFactory()->get()->getLanguageCode(), + "lang" => \OC::$server->getL10NFactory("")->get("")->getLanguageCode(), "mode" => ($callback === NULL ? "view" : "edit"), "user" => [ "id" => $userId, -- cgit v1.2.3 From ebfdf520daa222d61493d76a6f8b04ffe2ddc003 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Wed, 5 Apr 2017 18:03:27 +0300 Subject: fix adding token value --- controller/editorcontroller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/editorcontroller.php b/controller/editorcontroller.php index 08ed638..9ae01be 100644 --- a/controller/editorcontroller.php +++ b/controller/editorcontroller.php @@ -373,7 +373,7 @@ class EditorController extends Controller { if (!empty($this->config->GetDocumentServerSecret())) { $token = \Firebase\JWT\JWT::encode($params, $this->config->GetDocumentServerSecret()); - $params->token = $token; + $params["token"] = $token; } return $params; -- cgit v1.2.3 From 7957dc8360be0044655dae260a681556a49e18ec Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Wed, 5 Apr 2017 19:21:27 +0300 Subject: upd screenshots --- screenshots/icon.png | Bin 990 -> 587 bytes screenshots/main.png | Bin 68010 -> 68411 bytes screenshots/new.png | Bin 18956 -> 17772 bytes screenshots/settings.png | Bin 26685 -> 14761 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/screenshots/icon.png b/screenshots/icon.png index 8a648f2..03bc00a 100644 Binary files a/screenshots/icon.png and b/screenshots/icon.png differ diff --git a/screenshots/main.png b/screenshots/main.png index 1f2cb78..43e5017 100644 Binary files a/screenshots/main.png and b/screenshots/main.png differ diff --git a/screenshots/new.png b/screenshots/new.png index d318827..e25c939 100644 Binary files a/screenshots/new.png and b/screenshots/new.png differ diff --git a/screenshots/settings.png b/screenshots/settings.png index b054fd0..dd760dd 100644 Binary files a/screenshots/settings.png and b/screenshots/settings.png differ -- cgit v1.2.3 From 745c1edd243dbbb753a1fcf3ad7d3bb69a6afdea Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Thu, 6 Apr 2017 11:04:52 +0300 Subject: changelog 1.0.2 --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0cc51d..cd43420 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +# Change Log + +## 1.0.2 +### Added +- logging +- checking Document Server address on save +- checking version of onlyoffice +- set language of editor + +# Changed +- replace own Response class to OCP\AppFramework\Http class from core + +### Security +- jwt signature for request to Document Server + ## 1.0.1 - fix exception when versions app is disabled - adding protocol to document server url -- cgit v1.2.3 From f0d9b34cd8062099e63d231d5587ce350977e3b9 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Thu, 6 Apr 2017 14:38:02 +0300 Subject: setting fileType --- controller/editorcontroller.php | 1 + 1 file changed, 1 insertion(+) diff --git a/controller/editorcontroller.php b/controller/editorcontroller.php index 9ae01be..9253744 100644 --- a/controller/editorcontroller.php +++ b/controller/editorcontroller.php @@ -355,6 +355,7 @@ class EditorController extends Controller { $params = [ "document" => [ + "fileType" => pathinfo($fileName, PATHINFO_EXTENSION), "key" => DocumentService::GenerateRevisionId($key), "title" => $fileName, "url" => $fileUrl, -- cgit v1.2.3 From 25de35b9565db11ae7a8bdada61797b9edbf4357 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Thu, 6 Apr 2017 15:24:07 +0300 Subject: fix changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd43420..9db56e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ - checking version of onlyoffice - set language of editor -# Changed +### Changed - replace own Response class to OCP\AppFramework\Http class from core ### Security -- cgit v1.2.3