diff --git a/appinfo/application.php b/appinfo/application.php
index 5fd530a1..1d21f078 100644
--- a/appinfo/application.php
+++ b/appinfo/application.php
@@ -42,215 +42,215 @@
use OCA\Onlyoffice\Preview;
class Application extends App {
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- public $appConfig;
-
- /**
- * Hash generator
- *
- * @var Crypt
- */
- public $crypt;
-
- public function __construct(array $urlParams = []) {
- $appName = "onlyoffice";
-
- parent::__construct($appName, $urlParams);
-
- $this->appConfig = new AppConfig($appName);
- $this->crypt = new Crypt($this->appConfig);
-
- // Default script and style if configured
- $eventDispatcher = \OC::$server->getEventDispatcher();
- $eventDispatcher->addListener(
- "OCA\Files::loadAdditionalScripts",
- function () {
- if (!empty($this->appConfig->GetDocumentServerUrl())
- && $this->appConfig->SettingsAreSuccessful()
- && $this->appConfig->isUserAllowedToUse()) {
- Util::addScript("onlyoffice", "desktop");
- Util::addScript("onlyoffice", "main");
- Util::addScript("onlyoffice", "share");
- Util::addScript("onlyoffice", "template");
-
- if ($this->appConfig->GetSameTab()) {
- Util::addScript("onlyoffice", "listener");
- }
-
- Util::addStyle("onlyoffice", "template");
- Util::addStyle("onlyoffice", "main");
- }
- }
- );
-
- Util::connectHook("OCP\Share", "share_link_access", Hookhandler::class, "PublicPage");
-
- require_once __DIR__ . "/../3rdparty/jwt/BeforeValidException.php";
- require_once __DIR__ . "/../3rdparty/jwt/ExpiredException.php";
- require_once __DIR__ . "/../3rdparty/jwt/SignatureInvalidException.php";
- require_once __DIR__ . "/../3rdparty/jwt/CachedKeySet.php";
- require_once __DIR__ . "/../3rdparty/jwt/JWT.php";
- require_once __DIR__ . "/../3rdparty/jwt/JWK.php";
- require_once __DIR__ . "/../3rdparty/jwt/Key.php";
-
- // Set the leeway for the JWT library in case the system clock is a second off
- \Firebase\JWT\JWT::$leeway = $this->appConfig->GetJwtLeeway();
-
- $container = $this->getContainer();
-
- $detector = $container->query(IMimeTypeDetector::class);
- $detector->getAllMappings();
- $detector->registerType("ott", "application/vnd.oasis.opendocument.text-template");
- $detector->registerType("ots", "application/vnd.oasis.opendocument.spreadsheet-template");
- $detector->registerType("otp", "application/vnd.oasis.opendocument.presentation-template");
- $detector->registerType("docxf", "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf");
- $detector->registerType("oform", "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform");
-
- $previewManager = $container->query(IPreview::class);
- if ($this->appConfig->GetPreview()) {
- $previewManager->registerProvider(Preview::getMimeTypeRegex(), function () use ($container) {
- return $container->query(Preview::class);
- });
- }
-
- $notificationManager = \OC::$server->getNotificationManager();
- $notificationManager->registerNotifier(function () use ($appName) {
- return new Notifier(
- $appName,
- \OC::$server->getL10NFactory(),
- \OC::$server->getURLGenerator(),
- \OC::$server->getLogger(),
- \OC::$server->getUserManager()
- );
- }, function () use ($appName) {
- return [
- "id" => $appName,
- "name" => $appName,
- ];
- });
-
- $container->registerService("L10N", function ($c) {
- return $c->query("ServerContainer")->getL10N($c->query("AppName"));
- });
-
- $container->registerService("RootStorage", function ($c) {
- return $c->query("ServerContainer")->getRootFolder();
- });
-
- $container->registerService("UserSession", function ($c) {
- return $c->query("ServerContainer")->getUserSession();
- });
-
- $container->registerService("Logger", function ($c) {
- return $c->query("ServerContainer")->getLogger();
- });
-
- $container->registerService("URLGenerator", function ($c) {
- return $c->query("ServerContainer")->getURLGenerator();
- });
-
- // Controllers
- $container->registerService("SettingsController", function ($c) {
- return new SettingsController(
- $c->query("AppName"),
- $c->query("Request"),
- $c->query("URLGenerator"),
- $c->query("L10N"),
- $c->query("Logger"),
- $this->appConfig,
- $this->crypt
- );
- });
-
- $container->registerService("SettingsApiController", function ($c) {
- return new SettingsApiController(
- $c->query("AppName"),
- $c->query("Request"),
- $c->query("URLGenerator"),
- $this->appConfig
- );
- });
-
- $container->registerService("EditorController", function ($c) {
- return new EditorController(
- $c->query("AppName"),
- $c->query("Request"),
- $c->query("RootStorage"),
- $c->query("UserSession"),
- $c->query("ServerContainer")->getUserManager(),
- $c->query("URLGenerator"),
- $c->query("L10N"),
- $c->query("Logger"),
- $this->appConfig,
- $this->crypt,
- $c->query("IManager"),
- $c->query("Session"),
- $c->query("ServerContainer")->getGroupManager()
- );
- });
-
- $container->registerService("EditorApiController", function ($c) {
- return new EditorApiController(
- $c->query("AppName"),
- $c->query("Request"),
- $c->query("RootStorage"),
- $c->query("UserSession"),
- $c->query("URLGenerator"),
- $c->query("L10N"),
- $c->query("Logger"),
- $this->appConfig,
- $this->crypt,
- $c->query("IManager"),
- $c->query("Session"),
- $c->get(ITagManager::class)
- );
- });
-
- $container->registerService("CallbackController", function ($c) {
- return new CallbackController(
- $c->query("AppName"),
- $c->query("Request"),
- $c->query("RootStorage"),
- $c->query("UserSession"),
- $c->query("ServerContainer")->getUserManager(),
- $c->query("L10N"),
- $c->query("Logger"),
- $this->appConfig,
- $this->crypt,
- $c->query("IManager")
- );
- });
-
- $container->registerService("TemplateController", function ($c) {
- return new TemplateController(
- $c->query("AppName"),
- $c->query("Request"),
- $c->query("L10N"),
- $c->query("Logger")
- );
- });
-
- $container->registerService("WebAssetController", function ($c) {
- return new WebAssetController(
- $c->query("AppName"),
- $c->query("Request"),
- $c->query("Logger")
- );
- });
-
- $checkBackgroundJobs = new JobListController(
- $container->query("AppName"),
- $container->query("Request"),
- $container->query("Logger"),
- $this->appConfig,
- $container->query(IJobList::class)
- );
- $checkBackgroundJobs->checkAllJobs();
-
- Hooks::connectHooks();
- }
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ public $appConfig;
+
+ /**
+ * Hash generator
+ *
+ * @var Crypt
+ */
+ public $crypt;
+
+ public function __construct(array $urlParams = []) {
+ $appName = "onlyoffice";
+
+ parent::__construct($appName, $urlParams);
+
+ $this->appConfig = new AppConfig($appName);
+ $this->crypt = new Crypt($this->appConfig);
+
+ // Default script and style if configured
+ $eventDispatcher = \OC::$server->getEventDispatcher();
+ $eventDispatcher->addListener(
+ "OCA\Files::loadAdditionalScripts",
+ function () {
+ if (!empty($this->appConfig->GetDocumentServerUrl())
+ && $this->appConfig->SettingsAreSuccessful()
+ && $this->appConfig->isUserAllowedToUse()) {
+ Util::addScript("onlyoffice", "desktop");
+ Util::addScript("onlyoffice", "main");
+ Util::addScript("onlyoffice", "share");
+ Util::addScript("onlyoffice", "template");
+
+ if ($this->appConfig->GetSameTab()) {
+ Util::addScript("onlyoffice", "listener");
+ }
+
+ Util::addStyle("onlyoffice", "template");
+ Util::addStyle("onlyoffice", "main");
+ }
+ }
+ );
+
+ Util::connectHook("OCP\Share", "share_link_access", Hookhandler::class, "PublicPage");
+
+ require_once __DIR__ . "/../3rdparty/jwt/BeforeValidException.php";
+ require_once __DIR__ . "/../3rdparty/jwt/ExpiredException.php";
+ require_once __DIR__ . "/../3rdparty/jwt/SignatureInvalidException.php";
+ require_once __DIR__ . "/../3rdparty/jwt/CachedKeySet.php";
+ require_once __DIR__ . "/../3rdparty/jwt/JWT.php";
+ require_once __DIR__ . "/../3rdparty/jwt/JWK.php";
+ require_once __DIR__ . "/../3rdparty/jwt/Key.php";
+
+ // Set the leeway for the JWT library in case the system clock is a second off
+ \Firebase\JWT\JWT::$leeway = $this->appConfig->GetJwtLeeway();
+
+ $container = $this->getContainer();
+
+ $detector = $container->query(IMimeTypeDetector::class);
+ $detector->getAllMappings();
+ $detector->registerType("ott", "application/vnd.oasis.opendocument.text-template");
+ $detector->registerType("ots", "application/vnd.oasis.opendocument.spreadsheet-template");
+ $detector->registerType("otp", "application/vnd.oasis.opendocument.presentation-template");
+ $detector->registerType("docxf", "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf");
+ $detector->registerType("oform", "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform");
+
+ $previewManager = $container->query(IPreview::class);
+ if ($this->appConfig->GetPreview()) {
+ $previewManager->registerProvider(Preview::getMimeTypeRegex(), function () use ($container) {
+ return $container->query(Preview::class);
+ });
+ }
+
+ $notificationManager = \OC::$server->getNotificationManager();
+ $notificationManager->registerNotifier(function () use ($appName) {
+ return new Notifier(
+ $appName,
+ \OC::$server->getL10NFactory(),
+ \OC::$server->getURLGenerator(),
+ \OC::$server->getLogger(),
+ \OC::$server->getUserManager()
+ );
+ }, function () use ($appName) {
+ return [
+ "id" => $appName,
+ "name" => $appName,
+ ];
+ });
+
+ $container->registerService("L10N", function ($c) {
+ return $c->query("ServerContainer")->getL10N($c->query("AppName"));
+ });
+
+ $container->registerService("RootStorage", function ($c) {
+ return $c->query("ServerContainer")->getRootFolder();
+ });
+
+ $container->registerService("UserSession", function ($c) {
+ return $c->query("ServerContainer")->getUserSession();
+ });
+
+ $container->registerService("Logger", function ($c) {
+ return $c->query("ServerContainer")->getLogger();
+ });
+
+ $container->registerService("URLGenerator", function ($c) {
+ return $c->query("ServerContainer")->getURLGenerator();
+ });
+
+ // Controllers
+ $container->registerService("SettingsController", function ($c) {
+ return new SettingsController(
+ $c->query("AppName"),
+ $c->query("Request"),
+ $c->query("URLGenerator"),
+ $c->query("L10N"),
+ $c->query("Logger"),
+ $this->appConfig,
+ $this->crypt
+ );
+ });
+
+ $container->registerService("SettingsApiController", function ($c) {
+ return new SettingsApiController(
+ $c->query("AppName"),
+ $c->query("Request"),
+ $c->query("URLGenerator"),
+ $this->appConfig
+ );
+ });
+
+ $container->registerService("EditorController", function ($c) {
+ return new EditorController(
+ $c->query("AppName"),
+ $c->query("Request"),
+ $c->query("RootStorage"),
+ $c->query("UserSession"),
+ $c->query("ServerContainer")->getUserManager(),
+ $c->query("URLGenerator"),
+ $c->query("L10N"),
+ $c->query("Logger"),
+ $this->appConfig,
+ $this->crypt,
+ $c->query("IManager"),
+ $c->query("Session"),
+ $c->query("ServerContainer")->getGroupManager()
+ );
+ });
+
+ $container->registerService("EditorApiController", function ($c) {
+ return new EditorApiController(
+ $c->query("AppName"),
+ $c->query("Request"),
+ $c->query("RootStorage"),
+ $c->query("UserSession"),
+ $c->query("URLGenerator"),
+ $c->query("L10N"),
+ $c->query("Logger"),
+ $this->appConfig,
+ $this->crypt,
+ $c->query("IManager"),
+ $c->query("Session"),
+ $c->get(ITagManager::class)
+ );
+ });
+
+ $container->registerService("CallbackController", function ($c) {
+ return new CallbackController(
+ $c->query("AppName"),
+ $c->query("Request"),
+ $c->query("RootStorage"),
+ $c->query("UserSession"),
+ $c->query("ServerContainer")->getUserManager(),
+ $c->query("L10N"),
+ $c->query("Logger"),
+ $this->appConfig,
+ $this->crypt,
+ $c->query("IManager")
+ );
+ });
+
+ $container->registerService("TemplateController", function ($c) {
+ return new TemplateController(
+ $c->query("AppName"),
+ $c->query("Request"),
+ $c->query("L10N"),
+ $c->query("Logger")
+ );
+ });
+
+ $container->registerService("WebAssetController", function ($c) {
+ return new WebAssetController(
+ $c->query("AppName"),
+ $c->query("Request"),
+ $c->query("Logger")
+ );
+ });
+
+ $checkBackgroundJobs = new JobListController(
+ $container->query("AppName"),
+ $container->query("Request"),
+ $container->query("Logger"),
+ $this->appConfig,
+ $container->query(IJobList::class)
+ );
+ $checkBackgroundJobs->checkAllJobs();
+
+ Hooks::connectHooks();
+ }
}
diff --git a/appinfo/routes.php b/appinfo/routes.php
index 1f9b0199..82e0270a 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -18,40 +18,40 @@
*/
return [
- "routes" => [
- ["name" => "callback#download", "url" => "/download", "verb" => "GET"],
- ["name" => "callback#emptyfile", "url" => "/empty", "verb" => "GET"],
- ["name" => "callback#track", "url" => "/track", "verb" => "POST"],
- ["name" => "editor#create_new", "url" => "/new", "verb" => "GET"],
- ["name" => "editor#download", "url" => "/downloadas", "verb" => "GET"],
- ["name" => "editor#index", "url" => "/{fileId}", "verb" => "GET"],
- ["name" => "editor#public_page", "url" => "/s/{shareToken}", "verb" => "GET"],
- ["name" => "editor#users", "url" => "/ajax/users", "verb" => "GET"],
- ["name" => "editor#mention", "url" => "/ajax/mention", "verb" => "POST"],
- ["name" => "editor#reference", "url" => "/ajax/reference", "verb" => "POST"],
- ["name" => "editor#create", "url" => "/ajax/new", "verb" => "POST"],
- ["name" => "editor#convert", "url" => "/ajax/convert", "verb" => "POST"],
- ["name" => "editor#save", "url" => "/ajax/save", "verb" => "POST"],
- ["name" => "editor#url", "url" => "/ajax/url", "verb" => "GET"],
- ["name" => "editor#history", "url" => "/ajax/history", "verb" => "GET"],
- ["name" => "editor#version", "url" => "/ajax/version", "verb" => "GET"],
- ["name" => "editor#restore", "url" => "/ajax/restore", "verb" => "PUT"],
- ["name" => "settings#save_address", "url" => "/ajax/settings/address", "verb" => "PUT"],
- ["name" => "settings#save_common", "url" => "/ajax/settings/common", "verb" => "PUT"],
- ["name" => "settings#save_security", "url" => "/ajax/settings/security", "verb" => "PUT"],
- ["name" => "settings#get_settings", "url" => "/ajax/settings", "verb" => "GET"],
- ["name" => "settings#clear_history", "url" => "/ajax/settings/history", "verb" => "DELETE"],
- ["name" => "template#add_template", "url" => "/ajax/template", "verb" => "POST"],
- ["name" => "template#get_templates", "url" => "/ajax/template", "verb" => "GET"],
- ["name" => "template#delete_template", "url" => "/ajax/template", "verb" => "DELETE"],
- ["name" => "webasset#get", "url" => "/js/onlyoffice.js", "verb" => "GET"],
- ],
- "ocs" => [
- ["name" => "federation#key", "url" => "/api/v1/key", "verb" => "POST"],
- ["name" => "federation#keylock", "url" => "/api/v1/keylock", "verb" => "POST"],
- ["name" => "federation#healthcheck", "url" => "/api/v1/healthcheck", "verb" => "GET"],
- ["name" => "editorapi#config", "url" => "/api/v1/config/{fileId}", "verb" => "GET"],
- ["name" => "editorapi#fillempty", "url" => "/api/v1/empty/{fileId}", "verb" => "GET"],
- ["name" => "settingsapi#get_doc_server_url", "url" => "/api/v1/settings/docserver", "verb" => "GET"],
- ]
+ "routes" => [
+ ["name" => "callback#download", "url" => "/download", "verb" => "GET"],
+ ["name" => "callback#emptyfile", "url" => "/empty", "verb" => "GET"],
+ ["name" => "callback#track", "url" => "/track", "verb" => "POST"],
+ ["name" => "editor#create_new", "url" => "/new", "verb" => "GET"],
+ ["name" => "editor#download", "url" => "/downloadas", "verb" => "GET"],
+ ["name" => "editor#index", "url" => "/{fileId}", "verb" => "GET"],
+ ["name" => "editor#public_page", "url" => "/s/{shareToken}", "verb" => "GET"],
+ ["name" => "editor#users", "url" => "/ajax/users", "verb" => "GET"],
+ ["name" => "editor#mention", "url" => "/ajax/mention", "verb" => "POST"],
+ ["name" => "editor#reference", "url" => "/ajax/reference", "verb" => "POST"],
+ ["name" => "editor#create", "url" => "/ajax/new", "verb" => "POST"],
+ ["name" => "editor#convert", "url" => "/ajax/convert", "verb" => "POST"],
+ ["name" => "editor#save", "url" => "/ajax/save", "verb" => "POST"],
+ ["name" => "editor#url", "url" => "/ajax/url", "verb" => "GET"],
+ ["name" => "editor#history", "url" => "/ajax/history", "verb" => "GET"],
+ ["name" => "editor#version", "url" => "/ajax/version", "verb" => "GET"],
+ ["name" => "editor#restore", "url" => "/ajax/restore", "verb" => "PUT"],
+ ["name" => "settings#save_address", "url" => "/ajax/settings/address", "verb" => "PUT"],
+ ["name" => "settings#save_common", "url" => "/ajax/settings/common", "verb" => "PUT"],
+ ["name" => "settings#save_security", "url" => "/ajax/settings/security", "verb" => "PUT"],
+ ["name" => "settings#get_settings", "url" => "/ajax/settings", "verb" => "GET"],
+ ["name" => "settings#clear_history", "url" => "/ajax/settings/history", "verb" => "DELETE"],
+ ["name" => "template#add_template", "url" => "/ajax/template", "verb" => "POST"],
+ ["name" => "template#get_templates", "url" => "/ajax/template", "verb" => "GET"],
+ ["name" => "template#delete_template", "url" => "/ajax/template", "verb" => "DELETE"],
+ ["name" => "webasset#get", "url" => "/js/onlyoffice.js", "verb" => "GET"],
+ ],
+ "ocs" => [
+ ["name" => "federation#key", "url" => "/api/v1/key", "verb" => "POST"],
+ ["name" => "federation#keylock", "url" => "/api/v1/keylock", "verb" => "POST"],
+ ["name" => "federation#healthcheck", "url" => "/api/v1/healthcheck", "verb" => "GET"],
+ ["name" => "editorapi#config", "url" => "/api/v1/config/{fileId}", "verb" => "GET"],
+ ["name" => "editorapi#fillempty", "url" => "/api/v1/empty/{fileId}", "verb" => "GET"],
+ ["name" => "settingsapi#get_doc_server_url", "url" => "/api/v1/settings/docserver", "verb" => "GET"],
+ ]
];
diff --git a/controller/callbackcontroller.php b/controller/callbackcontroller.php
index fec40cea..f9e1509e 100644
--- a/controller/callbackcontroller.php
+++ b/controller/callbackcontroller.php
@@ -52,735 +52,735 @@
* Save the file without authentication.
*/
class CallbackController extends Controller {
- /**
- * Root folder
- *
- * @var IRootFolder
- */
- private $root;
-
- /**
- * User session
- *
- * @var IUserSession
- */
- private $userSession;
-
- /**
- * User manager
- *
- * @var IUserManager
- */
- private $userManager;
-
- /**
- * l10n service
- *
- * @var IL10N
- */
- private $trans;
-
- /**
- * Logger
- *
- * @var OCP\ILogger
- */
- private $logger;
-
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- private $config;
-
- /**
- * Hash generator
- *
- * @var Crypt
- */
- private $crypt;
-
- /**
- * Share manager
- *
- * @var IManager
- */
- private $shareManager;
-
- /**
- * File version manager
- *
- * @var VersionManager
- */
- private $versionManager;
-
- /**
- * Status of the document
- */
- private const TrackerStatus_Editing = 1;
- private const TrackerStatus_MustSave = 2;
- private const TrackerStatus_Corrupted = 3;
- private const TrackerStatus_Closed = 4;
- private const TrackerStatus_ForceSave = 6;
- private const TrackerStatus_CorruptedForceSave = 7;
-
- /**
- * @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 AppConfig $config - application configuration
- * @param Crypt $crypt - hash generator
- * @param IManager $shareManager - Share manager
- */
- public function __construct(
- $AppName,
- IRequest $request,
- IRootFolder $root,
- IUserSession $userSession,
- IUserManager $userManager,
- IL10N $trans,
- ILogger $logger,
- AppConfig $config,
- Crypt $crypt,
- IManager $shareManager
- ) {
- parent::__construct($AppName, $request);
-
- $this->root = $root;
- $this->userSession = $userSession;
- $this->userManager = $userManager;
- $this->trans = $trans;
- $this->logger = $logger;
- $this->config = $config;
- $this->crypt = $crypt;
- $this->shareManager = $shareManager;
-
- $this->versionManager = new VersionManager($AppName, $root);
- }
-
- /**
- * Downloading file by the document service
- *
- * @param string $doc - verification token with the file identifier
- *
- * @return DataDownloadResponse|JSONResponse
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- * @PublicPage
- * @CORS
- */
- public function download($doc) {
- list($hashData, $error) = $this->crypt->ReadHash($doc);
- if ($hashData === null) {
- $this->logger->error("Download with empty or not correct hash: $error", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
- }
- if ($hashData->action !== "download") {
- $this->logger->error("Download with other action", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_BAD_REQUEST);
- }
-
- $fileId = $hashData->fileId;
- $version = isset($hashData->version) ? $hashData->version : null;
- $changes = isset($hashData->changes) ? $hashData->changes : false;
- $template = isset($hashData->template) ? $hashData->template : false;
- $this->logger->debug("Download: $fileId ($version)" . ($changes ? " changes" : ""), ["app" => $this->appName]);
-
- if (!$this->userSession->isLoggedIn()
- && !$changes) {
- if (!empty($this->config->GetDocumentServerSecret())) {
- $header = \OC::$server->getRequest()->getHeader($this->config->JwtHeader());
- if (empty($header)) {
- $this->logger->error("Download without jwt", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
- }
-
- $header = substr($header, \strlen("Bearer "));
-
- try {
- $decodedHeader = \Firebase\JWT\JWT::decode($header, new \Firebase\JWT\Key($this->config->GetDocumentServerSecret(), "HS256"));
- } catch (\UnexpectedValueException $e) {
- $this->logger->logException($e, ["message" => "Download with invalid jwt", "app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
- }
- }
- }
-
- $userId = null;
-
- $user = null;
- if ($this->userSession->isLoggedIn()) {
- $user = $this->userSession->getUser();
- $userId = $user->getUID();
- } else {
- \OC_Util::tearDownFS();
-
- if (isset($hashData->userId)) {
- $userId = $hashData->userId;
-
- $user = $this->userManager->get($userId);
- if (!empty($user)) {
- \OC_User::setUserId($userId);
- }
-
- if ($this->config->checkEncryptionModule() === "master") {
- \OC_User::setIncognitoMode(true);
- } else {
- if (!empty($user)) {
- \OC_Util::setupFS($userId);
- }
- }
- }
- }
-
- $shareToken = isset($hashData->shareToken) ? $hashData->shareToken : null;
- list($file, $error) = empty($shareToken) ? $this->getFile($userId, $fileId, null, $changes ? null : $version, $template) : $this->getFileByToken($fileId, $shareToken, $changes ? null : $version);
-
- if (isset($error)) {
- return $error;
- }
-
- if ($this->userSession->isLoggedIn() && !$file->isReadable()) {
- $this->logger->error("Download without access right", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
- }
-
- if (empty($user)
- && $this->config->checkEncryptionModule() !== "master") {
- $owner = $file->getFileInfo()->getOwner();
- if ($owner !== null) {
- \OC_Util::setupFS($owner->getUID());
- }
- }
-
- if ($changes) {
- if ($this->versionManager->available !== true) {
- $this->logger->error("Download changes: versionManager is null", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_BAD_REQUEST);
- }
-
- $owner = $file->getFileInfo()->getOwner();
- if ($owner === null) {
- $this->logger->error("Download: changes owner of $fileId was not found", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Files not found")], Http::STATUS_NOT_FOUND);
- }
-
- $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
-
- $versionId = null;
- if ($version > \count($versions)) {
- $versionId = $file->getFileInfo()->getMtime();
- } else {
- $fileVersion = array_values($versions)[$version - 1];
-
- $versionId = $fileVersion->getRevisionId();
- }
-
- $changesFile = FileVersions::getChangesFile($owner->getUID(), $fileId, $versionId);
- if ($changesFile === null) {
- $this->logger->error("Download: changes $fileId ($version) was not found", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Files not found")], Http::STATUS_NOT_FOUND);
- }
-
- $file = $changesFile;
- }
-
- try {
- $response = new DataDownloadResponse($file->getContent(), $file->getName(), $file->getMimeType());
-
- if ($changes) {
- $response = \OC_Response::setOptionsRequestHeaders($response);
- }
-
- return $response;
- } catch (NotPermittedException $e) {
- $this->logger->logException($e, ["message" => "Download Not permitted: $fileId ($version)", "app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Not permitted")], Http::STATUS_FORBIDDEN);
- }
- return new JSONResponse(["message" => $this->trans->t("Download failed")], Http::STATUS_INTERNAL_SERVER_ERROR);
- }
-
- /**
- * Downloading empty file by the document service
- *
- * @param string $doc - verification token with the file identifier
- *
- * @return DataDownloadResponse|JSONResponse
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- * @PublicPage
- * @CORS
- */
- public function emptyfile($doc) {
- $this->logger->debug("Download empty", ["app" => $this->appName]);
-
- list($hashData, $error) = $this->crypt->ReadHash($doc);
- if ($hashData === null) {
- $this->logger->error("Download empty with empty or not correct hash: $error", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
- }
- if ($hashData->action !== "empty") {
- $this->logger->error("Download empty with other action", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_BAD_REQUEST);
- }
-
- if (!empty($this->config->GetDocumentServerSecret())) {
- $header = \OC::$server->getRequest()->getHeader($this->config->JwtHeader());
- if (empty($header)) {
- $this->logger->error("Download empty without jwt", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
- }
-
- $header = substr($header, \strlen("Bearer "));
-
- try {
- $decodedHeader = \Firebase\JWT\JWT::decode($header, new \Firebase\JWT\Key($this->config->GetDocumentServerSecret(), "HS256"));
- } catch (\UnexpectedValueException $e) {
- $this->logger->logException($e, ["message" => "Download empty with invalid jwt", "app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
- }
- }
-
- $templatePath = TemplateManager::GetEmptyTemplatePath("en", ".docx");
-
- $template = file_get_contents($templatePath);
- if (!$template) {
- $this->logger->info("Template for download empty not found: $templatePath", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("File not found")], Http::STATUS_NOT_FOUND);
- }
-
- try {
- return new DataDownloadResponse($template, "new.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
- } catch (NotPermittedException $e) {
- $this->logger->logException($e, ["message" => "Download Not permitted", "app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Not permitted")], Http::STATUS_FORBIDDEN);
- }
- return new JSONResponse(["message" => $this->trans->t("Download failed")], Http::STATUS_INTERNAL_SERVER_ERROR);
- }
-
- /**
- * Handle request from the document server with the document status information
- *
- * @param string $doc - verification token with the file identifier
- * @param array $users - the list of the identifiers of the users
- * @param string $key - the edited document identifier
- * @param integer $status - the edited status
- * @param string $url - the link to the edited document to be saved
- * @param string $token - request signature
- * @param array $history - file history
- * @param string $changesurl - link to file changes
- * @param integer $forcesavetype - the type of force save action
- * @param array $actions - the array of action
- * @param string $filetype - extension of the document that is downloaded from the link specified with the url parameter
- *
- * @return array
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- * @PublicPage
- * @CORS
- */
- public function track($doc, $users, $key, $status, $url, $token, $history, $changesurl, $forcesavetype, $actions, $filetype) {
- list($hashData, $error) = $this->crypt->ReadHash($doc);
- if ($hashData === null) {
- $this->logger->error("Track with empty or not correct hash: $error", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
- }
- if ($hashData->action !== "track") {
- $this->logger->error("Track with other action", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_BAD_REQUEST);
- }
-
- $fileId = $hashData->fileId;
- $this->logger->debug("Track: $fileId status $status", ["app" => $this->appName]);
-
- if (!empty($this->config->GetDocumentServerSecret())) {
- if (!empty($token)) {
- try {
- $payload = \Firebase\JWT\JWT::decode($token, new \Firebase\JWT\Key($this->config->GetDocumentServerSecret(), "HS256"));
- } catch (\UnexpectedValueException $e) {
- $this->logger->logException($e, ["message" => "Track with invalid jwt in body", "app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
- }
- } else {
- $header = \OC::$server->getRequest()->getHeader($this->config->JwtHeader());
- if (empty($header)) {
- $this->logger->error("Track without jwt", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
- }
-
- $header = substr($header, \strlen("Bearer "));
-
- try {
- $decodedHeader = \Firebase\JWT\JWT::decode($header, new \Firebase\JWT\Key($this->config->GetDocumentServerSecret(), "HS256"));
-
- $payload = $decodedHeader->payload;
- } catch (\UnexpectedValueException $e) {
- $this->logger->logException($e, ["message" => "Track with invalid jwt", "app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
- }
- }
-
- $users = isset($payload->users) ? $payload->users : null;
- $key = $payload->key;
- $status = $payload->status;
- $url = isset($payload->url) ? $payload->url : null;
- }
-
- $result = 1;
- switch ($status) {
- case self::TrackerStatus_MustSave:
- case self::TrackerStatus_Corrupted:
- case self::TrackerStatus_ForceSave:
- case self::TrackerStatus_CorruptedForceSave:
- if (empty($url)) {
- $this->logger->error("Track without url: $fileId status $status", ["app" => $this->appName]);
- return new JSONResponse(["message" => "Url not found"], Http::STATUS_BAD_REQUEST);
- }
-
- try {
- $shareToken = isset($hashData->shareToken) ? $hashData->shareToken : null;
- $filePath = null;
-
- \OC_Util::tearDownFS();
-
- $isForcesave = $status === self::TrackerStatus_ForceSave || $status === self::TrackerStatus_CorruptedForceSave;
-
- // author of the latest changes
- $userId = $this->parseUserId($users[0]);
-
- if ($isForcesave
- && $forcesavetype === 1
- && !empty($actions)) {
- // the user who clicked Save
- $userId = $this->parseUserId($actions[0]["userid"]);
- }
-
- $user = $this->userManager->get($userId);
- if (!empty($user)) {
- \OC_User::setUserId($userId);
- } else {
- if (empty($shareToken)) {
- $this->logger->error("Track without token: $fileId status $status", ["app" => $this->appName]);
- return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
- }
-
- $this->logger->debug("Track $fileId by token for $userId", ["app" => $this->appName]);
- }
-
- // owner of file from the callback link
- $ownerId = $hashData->ownerId;
- $owner = $this->userManager->get($ownerId);
-
- if (!empty($owner)) {
- $userId = $ownerId;
- } else {
- $callbackUserId = $hashData->userId;
- $callbackUser = $this->userManager->get($callbackUserId);
-
- if (!empty($callbackUser)) {
- // author of the callback link
- $userId = $callbackUserId;
-
- // path for author of the callback link
- $filePath = $hashData->filePath;
- }
- }
-
- if ($this->config->checkEncryptionModule() === "master") {
- \OC_User::setIncognitoMode(true);
- } elseif (!empty($userId)) {
- \OC_Util::setupFS($userId);
- }
-
- 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()), ["app" => $this->appName]);
- return $error;
- }
-
- $url = $this->config->ReplaceDocumentServerUrlToInternal($url);
-
- $prevVersion = $file->getFileInfo()->getMtime();
- $fileName = $file->getName();
- $curExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
- $downloadExt = $filetype;
-
- $documentService = new DocumentService($this->trans, $this->config);
- if ($downloadExt !== $curExt) {
- $key = DocumentService::GenerateRevisionId($fileId . $url);
-
- try {
- $this->logger->debug("Converted from $downloadExt to $curExt", ["app" => $this->appName]);
- $url = $documentService->GetConvertedUri($url, $downloadExt, $curExt, $key);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "Converted on save error", "app" => $this->appName]);
- return new JSONResponse(["message" => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
- }
- }
-
- $newData = $documentService->Request($url);
-
- $prevIsForcesave = KeyManager::wasForcesave($fileId);
-
- if (RemoteInstance::isRemoteFile($file)) {
- $isLock = RemoteInstance::lockRemoteKey($file, $isForcesave, null);
- if ($isForcesave && !$isLock) {
- break;
- }
- } else {
- KeyManager::lock($fileId, $isForcesave);
- }
-
- $this->logger->debug("Track put content " . $file->getPath(), ["app" => $this->appName]);
- $this->retryOperation(function () use ($file, $newData) {
- return $file->putContent($newData);
- });
-
- if (RemoteInstance::isRemoteFile($file)) {
- if ($isForcesave) {
- RemoteInstance::lockRemoteKey($file, false, $isForcesave);
- }
- } else {
- KeyManager::lock($fileId, false);
- KeyManager::setForcesave($fileId, $isForcesave);
- }
-
- if (!$isForcesave
- && !$prevIsForcesave
- && $this->versionManager->available
- && $this->config->GetVersionHistory()) {
- $changes = null;
- if (!empty($changesurl)) {
- $changesurl = $this->config->ReplaceDocumentServerUrlToInternal($changesurl);
- $changes = $documentService->Request($changesurl);
- }
- FileVersions::saveHistory($file->getFileInfo(), $history, $changes, $prevVersion);
- }
-
- if (!empty($user) && $this->config->GetVersionHistory()) {
- FileVersions::saveAuthor($file->getFileInfo(), $user);
- }
-
- if ($this->config->checkEncryptionModule() === "master"
- && !$isForcesave) {
- KeyManager::delete($fileId);
- }
-
- $result = 0;
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "Track: $fileId status $status error", "app" => $this->appName]);
- }
- break;
-
- case self::TrackerStatus_Editing:
- case self::TrackerStatus_Closed:
- $result = 0;
- break;
- }
-
- $this->logger->debug("Track: $fileId status $status result $result", ["app" => $this->appName]);
-
- return new JSONResponse(["error" => $result], Http::STATUS_OK);
- }
-
- /**
- * Getting file by identifier
- *
- * @param string $userId - user identifier
- * @param integer $fileId - file identifier
- * @param string $filePath - file path
- * @param integer $version - file version
- * @param bool $template - file is template
- *
- * @return array
- */
- private function getFile($userId, $fileId, $filePath = null, $version = 0, $template = false) {
- if (empty($fileId)) {
- return [null, new JSONResponse(["message" => $this->trans->t("FileId is empty")], Http::STATUS_BAD_REQUEST)];
- }
-
- try {
- $folder = !$template ? $this->root->getUserFolder($userId) : TemplateManager::GetGlobalTemplateDir();
- $files = $folder->getById($fileId);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "getFile: $fileId", "app" => $this->appName]);
- return [null, new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_BAD_REQUEST)];
- }
-
- if (empty($files)) {
- $this->logger->error("Files not found: $fileId", ["app" => $this->appName]);
- return [null, new JSONResponse(["message" => $this->trans->t("Files not found")], Http::STATUS_NOT_FOUND)];
- }
-
- $file = $files[0];
-
- if (\count($files) > 1 && !empty($filePath)) {
- $filePath = "/" . $userId . "/files" . $filePath;
- foreach ($files as $curFile) {
- if ($curFile->getPath() === $filePath) {
- $file = $curFile;
- break;
- }
- }
- }
-
- if (!($file instanceof File)) {
- $this->logger->error("File not found: $fileId", ["app" => $this->appName]);
- return [null, new JSONResponse(["message" => $this->trans->t("File not found")], Http::STATUS_NOT_FOUND)];
- }
-
- if ($version > 0 && $this->versionManager->available) {
- $owner = $file->getFileInfo()->getOwner();
-
- if ($owner !== null) {
- if ($owner->getUID() !== $userId) {
- list($file, $error) = $this->getFile($owner->getUID(), $file->getId());
-
- if (isset($error)) {
- return [null, $error];
- }
- }
-
- $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
-
- if ($version <= \count($versions)) {
- $fileVersion = array_values($versions)[$version - 1];
- $file = $this->versionManager->getVersionFile($owner, $file->getFileInfo(), $fileVersion->getRevisionId());
- }
- }
- }
-
- return [$file, null];
- }
-
- /**
- * Getting file by token
- *
- * @param integer $fileId - file identifier
- * @param string $shareToken - access token
- * @param integer $version - file version
- *
- * @return array
- */
- private function getFileByToken($fileId, $shareToken, $version = 0) {
- list($share, $error) = $this->getShare($shareToken);
-
- if (isset($error)) {
- return [null, $error];
- }
-
- try {
- $node = $share->getNode();
- } catch (NotFoundException $e) {
- $this->logger->logException($e, ["message" => "getFileByToken error", "app" => $this->appName]);
- return [null, new JSONResponse(["message" => $this->trans->t("File not found")], Http::STATUS_NOT_FOUND)];
- }
-
- if ($node instanceof Folder) {
- try {
- $files = $node->getById($fileId);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "getFileByToken: $fileId", "app" => $this->appName]);
- return [null, new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_NOT_FOUND)];
- }
-
- if (empty($files)) {
- return [null, new JSONResponse(["message" => $this->trans->t("File not found")], Http::STATUS_NOT_FOUND)];
- }
- $file = $files[0];
- } else {
- $file = $node;
- }
-
- if ($version > 0 && $this->versionManager->available) {
- $owner = $file->getFileInfo()->getOwner();
-
- if ($owner !== null) {
- $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
-
- if ($version <= \count($versions)) {
- $fileVersion = array_values($versions)[$version - 1];
- $file = $this->versionManager->getVersionFile($owner, $file->getFileInfo(), $fileVersion->getRevisionId());
- }
- }
- }
-
- return [$file, null];
- }
-
- /**
- * Getting share by token
- *
- * @param string $shareToken - access token
- *
- * @return array
- */
- private function getShare($shareToken) {
- if (empty($shareToken)) {
- return [null, new JSONResponse(["message" => $this->trans->t("FileId is empty")], Http::STATUS_BAD_REQUEST)];
- }
-
- $share = null;
- try {
- $share = $this->shareManager->getShareByToken($shareToken);
- } catch (ShareNotFound $e) {
- $this->logger->logException($e, ["message" => "getShare error", "app" => $this->appName]);
- $share = null;
- }
-
- if ($share === null || $share === false) {
- return [null, new JSONResponse(["message" => $this->trans->t("You do not have enough permissions to view the file")], Http::STATUS_FORBIDDEN)];
- }
-
- return [$share, null];
- }
-
- /**
- * Parse user identifier for current instance
- *
- * @param string $userId - unique user identifier
- *
- * @return string
- */
- private function parseUserId($userId) {
- $instanceId = $this->config->GetSystemValue("instanceid", true);
- $instanceId = $instanceId . "_";
-
- if (substr($userId, 0, \strlen($instanceId)) === $instanceId) {
- return substr($userId, \strlen($instanceId));
- }
-
- return $userId;
- }
-
- /**
- * Retry operation if a LockedException occurred
- * Other exceptions will still be thrown
- *
- * @param callable $operation
- *
- * @throws LockedException
- */
- private function retryOperation(callable $operation) {
- $i = 0;
- while (true) {
- try {
- return $operation();
- } catch (LockedException $e) {
- if (++$i === 4) {
- throw $e;
- }
- }
- usleep(500000);
- }
- }
+ /**
+ * Root folder
+ *
+ * @var IRootFolder
+ */
+ private $root;
+
+ /**
+ * User session
+ *
+ * @var IUserSession
+ */
+ private $userSession;
+
+ /**
+ * User manager
+ *
+ * @var IUserManager
+ */
+ private $userManager;
+
+ /**
+ * l10n service
+ *
+ * @var IL10N
+ */
+ private $trans;
+
+ /**
+ * Logger
+ *
+ * @var OCP\ILogger
+ */
+ private $logger;
+
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ private $config;
+
+ /**
+ * Hash generator
+ *
+ * @var Crypt
+ */
+ private $crypt;
+
+ /**
+ * Share manager
+ *
+ * @var IManager
+ */
+ private $shareManager;
+
+ /**
+ * File version manager
+ *
+ * @var VersionManager
+ */
+ private $versionManager;
+
+ /**
+ * Status of the document
+ */
+ private const TrackerStatus_Editing = 1;
+ private const TrackerStatus_MustSave = 2;
+ private const TrackerStatus_Corrupted = 3;
+ private const TrackerStatus_Closed = 4;
+ private const TrackerStatus_ForceSave = 6;
+ private const TrackerStatus_CorruptedForceSave = 7;
+
+ /**
+ * @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 AppConfig $config - application configuration
+ * @param Crypt $crypt - hash generator
+ * @param IManager $shareManager - Share manager
+ */
+ public function __construct(
+ $AppName,
+ IRequest $request,
+ IRootFolder $root,
+ IUserSession $userSession,
+ IUserManager $userManager,
+ IL10N $trans,
+ ILogger $logger,
+ AppConfig $config,
+ Crypt $crypt,
+ IManager $shareManager
+ ) {
+ parent::__construct($AppName, $request);
+
+ $this->root = $root;
+ $this->userSession = $userSession;
+ $this->userManager = $userManager;
+ $this->trans = $trans;
+ $this->logger = $logger;
+ $this->config = $config;
+ $this->crypt = $crypt;
+ $this->shareManager = $shareManager;
+
+ $this->versionManager = new VersionManager($AppName, $root);
+ }
+
+ /**
+ * Downloading file by the document service
+ *
+ * @param string $doc - verification token with the file identifier
+ *
+ * @return DataDownloadResponse|JSONResponse
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
+ * @CORS
+ */
+ public function download($doc) {
+ list($hashData, $error) = $this->crypt->ReadHash($doc);
+ if ($hashData === null) {
+ $this->logger->error("Download with empty or not correct hash: $error", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
+ }
+ if ($hashData->action !== "download") {
+ $this->logger->error("Download with other action", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_BAD_REQUEST);
+ }
+
+ $fileId = $hashData->fileId;
+ $version = isset($hashData->version) ? $hashData->version : null;
+ $changes = isset($hashData->changes) ? $hashData->changes : false;
+ $template = isset($hashData->template) ? $hashData->template : false;
+ $this->logger->debug("Download: $fileId ($version)" . ($changes ? " changes" : ""), ["app" => $this->appName]);
+
+ if (!$this->userSession->isLoggedIn()
+ && !$changes) {
+ if (!empty($this->config->GetDocumentServerSecret())) {
+ $header = \OC::$server->getRequest()->getHeader($this->config->JwtHeader());
+ if (empty($header)) {
+ $this->logger->error("Download without jwt", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
+ }
+
+ $header = substr($header, \strlen("Bearer "));
+
+ try {
+ $decodedHeader = \Firebase\JWT\JWT::decode($header, new \Firebase\JWT\Key($this->config->GetDocumentServerSecret(), "HS256"));
+ } catch (\UnexpectedValueException $e) {
+ $this->logger->logException($e, ["message" => "Download with invalid jwt", "app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
+ }
+ }
+ }
+
+ $userId = null;
+
+ $user = null;
+ if ($this->userSession->isLoggedIn()) {
+ $user = $this->userSession->getUser();
+ $userId = $user->getUID();
+ } else {
+ \OC_Util::tearDownFS();
+
+ if (isset($hashData->userId)) {
+ $userId = $hashData->userId;
+
+ $user = $this->userManager->get($userId);
+ if (!empty($user)) {
+ \OC_User::setUserId($userId);
+ }
+
+ if ($this->config->checkEncryptionModule() === "master") {
+ \OC_User::setIncognitoMode(true);
+ } else {
+ if (!empty($user)) {
+ \OC_Util::setupFS($userId);
+ }
+ }
+ }
+ }
+
+ $shareToken = isset($hashData->shareToken) ? $hashData->shareToken : null;
+ list($file, $error) = empty($shareToken) ? $this->getFile($userId, $fileId, null, $changes ? null : $version, $template) : $this->getFileByToken($fileId, $shareToken, $changes ? null : $version);
+
+ if (isset($error)) {
+ return $error;
+ }
+
+ if ($this->userSession->isLoggedIn() && !$file->isReadable()) {
+ $this->logger->error("Download without access right", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
+ }
+
+ if (empty($user)
+ && $this->config->checkEncryptionModule() !== "master") {
+ $owner = $file->getFileInfo()->getOwner();
+ if ($owner !== null) {
+ \OC_Util::setupFS($owner->getUID());
+ }
+ }
+
+ if ($changes) {
+ if ($this->versionManager->available !== true) {
+ $this->logger->error("Download changes: versionManager is null", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_BAD_REQUEST);
+ }
+
+ $owner = $file->getFileInfo()->getOwner();
+ if ($owner === null) {
+ $this->logger->error("Download: changes owner of $fileId was not found", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Files not found")], Http::STATUS_NOT_FOUND);
+ }
+
+ $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
+
+ $versionId = null;
+ if ($version > \count($versions)) {
+ $versionId = $file->getFileInfo()->getMtime();
+ } else {
+ $fileVersion = array_values($versions)[$version - 1];
+
+ $versionId = $fileVersion->getRevisionId();
+ }
+
+ $changesFile = FileVersions::getChangesFile($owner->getUID(), $fileId, $versionId);
+ if ($changesFile === null) {
+ $this->logger->error("Download: changes $fileId ($version) was not found", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Files not found")], Http::STATUS_NOT_FOUND);
+ }
+
+ $file = $changesFile;
+ }
+
+ try {
+ $response = new DataDownloadResponse($file->getContent(), $file->getName(), $file->getMimeType());
+
+ if ($changes) {
+ $response = \OC_Response::setOptionsRequestHeaders($response);
+ }
+
+ return $response;
+ } catch (NotPermittedException $e) {
+ $this->logger->logException($e, ["message" => "Download Not permitted: $fileId ($version)", "app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Not permitted")], Http::STATUS_FORBIDDEN);
+ }
+ return new JSONResponse(["message" => $this->trans->t("Download failed")], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+
+ /**
+ * Downloading empty file by the document service
+ *
+ * @param string $doc - verification token with the file identifier
+ *
+ * @return DataDownloadResponse|JSONResponse
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
+ * @CORS
+ */
+ public function emptyfile($doc) {
+ $this->logger->debug("Download empty", ["app" => $this->appName]);
+
+ list($hashData, $error) = $this->crypt->ReadHash($doc);
+ if ($hashData === null) {
+ $this->logger->error("Download empty with empty or not correct hash: $error", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
+ }
+ if ($hashData->action !== "empty") {
+ $this->logger->error("Download empty with other action", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_BAD_REQUEST);
+ }
+
+ if (!empty($this->config->GetDocumentServerSecret())) {
+ $header = \OC::$server->getRequest()->getHeader($this->config->JwtHeader());
+ if (empty($header)) {
+ $this->logger->error("Download empty without jwt", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
+ }
+
+ $header = substr($header, \strlen("Bearer "));
+
+ try {
+ $decodedHeader = \Firebase\JWT\JWT::decode($header, new \Firebase\JWT\Key($this->config->GetDocumentServerSecret(), "HS256"));
+ } catch (\UnexpectedValueException $e) {
+ $this->logger->logException($e, ["message" => "Download empty with invalid jwt", "app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
+ }
+ }
+
+ $templatePath = TemplateManager::GetEmptyTemplatePath("en", ".docx");
+
+ $template = file_get_contents($templatePath);
+ if (!$template) {
+ $this->logger->info("Template for download empty not found: $templatePath", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("File not found")], Http::STATUS_NOT_FOUND);
+ }
+
+ try {
+ return new DataDownloadResponse($template, "new.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
+ } catch (NotPermittedException $e) {
+ $this->logger->logException($e, ["message" => "Download Not permitted", "app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Not permitted")], Http::STATUS_FORBIDDEN);
+ }
+ return new JSONResponse(["message" => $this->trans->t("Download failed")], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+
+ /**
+ * Handle request from the document server with the document status information
+ *
+ * @param string $doc - verification token with the file identifier
+ * @param array $users - the list of the identifiers of the users
+ * @param string $key - the edited document identifier
+ * @param integer $status - the edited status
+ * @param string $url - the link to the edited document to be saved
+ * @param string $token - request signature
+ * @param array $history - file history
+ * @param string $changesurl - link to file changes
+ * @param integer $forcesavetype - the type of force save action
+ * @param array $actions - the array of action
+ * @param string $filetype - extension of the document that is downloaded from the link specified with the url parameter
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
+ * @CORS
+ */
+ public function track($doc, $users, $key, $status, $url, $token, $history, $changesurl, $forcesavetype, $actions, $filetype) {
+ list($hashData, $error) = $this->crypt->ReadHash($doc);
+ if ($hashData === null) {
+ $this->logger->error("Track with empty or not correct hash: $error", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
+ }
+ if ($hashData->action !== "track") {
+ $this->logger->error("Track with other action", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_BAD_REQUEST);
+ }
+
+ $fileId = $hashData->fileId;
+ $this->logger->debug("Track: $fileId status $status", ["app" => $this->appName]);
+
+ if (!empty($this->config->GetDocumentServerSecret())) {
+ if (!empty($token)) {
+ try {
+ $payload = \Firebase\JWT\JWT::decode($token, new \Firebase\JWT\Key($this->config->GetDocumentServerSecret(), "HS256"));
+ } catch (\UnexpectedValueException $e) {
+ $this->logger->logException($e, ["message" => "Track with invalid jwt in body", "app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
+ }
+ } else {
+ $header = \OC::$server->getRequest()->getHeader($this->config->JwtHeader());
+ if (empty($header)) {
+ $this->logger->error("Track without jwt", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
+ }
+
+ $header = substr($header, \strlen("Bearer "));
+
+ try {
+ $decodedHeader = \Firebase\JWT\JWT::decode($header, new \Firebase\JWT\Key($this->config->GetDocumentServerSecret(), "HS256"));
+
+ $payload = $decodedHeader->payload;
+ } catch (\UnexpectedValueException $e) {
+ $this->logger->logException($e, ["message" => "Track with invalid jwt", "app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
+ }
+ }
+
+ $users = isset($payload->users) ? $payload->users : null;
+ $key = $payload->key;
+ $status = $payload->status;
+ $url = isset($payload->url) ? $payload->url : null;
+ }
+
+ $result = 1;
+ switch ($status) {
+ case self::TrackerStatus_MustSave:
+ case self::TrackerStatus_Corrupted:
+ case self::TrackerStatus_ForceSave:
+ case self::TrackerStatus_CorruptedForceSave:
+ if (empty($url)) {
+ $this->logger->error("Track without url: $fileId status $status", ["app" => $this->appName]);
+ return new JSONResponse(["message" => "Url not found"], Http::STATUS_BAD_REQUEST);
+ }
+
+ try {
+ $shareToken = isset($hashData->shareToken) ? $hashData->shareToken : null;
+ $filePath = null;
+
+ \OC_Util::tearDownFS();
+
+ $isForcesave = $status === self::TrackerStatus_ForceSave || $status === self::TrackerStatus_CorruptedForceSave;
+
+ // author of the latest changes
+ $userId = $this->parseUserId($users[0]);
+
+ if ($isForcesave
+ && $forcesavetype === 1
+ && !empty($actions)) {
+ // the user who clicked Save
+ $userId = $this->parseUserId($actions[0]["userid"]);
+ }
+
+ $user = $this->userManager->get($userId);
+ if (!empty($user)) {
+ \OC_User::setUserId($userId);
+ } else {
+ if (empty($shareToken)) {
+ $this->logger->error("Track without token: $fileId status $status", ["app" => $this->appName]);
+ return new JSONResponse(["message" => $this->trans->t("Access denied")], Http::STATUS_FORBIDDEN);
+ }
+
+ $this->logger->debug("Track $fileId by token for $userId", ["app" => $this->appName]);
+ }
+
+ // owner of file from the callback link
+ $ownerId = $hashData->ownerId;
+ $owner = $this->userManager->get($ownerId);
+
+ if (!empty($owner)) {
+ $userId = $ownerId;
+ } else {
+ $callbackUserId = $hashData->userId;
+ $callbackUser = $this->userManager->get($callbackUserId);
+
+ if (!empty($callbackUser)) {
+ // author of the callback link
+ $userId = $callbackUserId;
+
+ // path for author of the callback link
+ $filePath = $hashData->filePath;
+ }
+ }
+
+ if ($this->config->checkEncryptionModule() === "master") {
+ \OC_User::setIncognitoMode(true);
+ } elseif (!empty($userId)) {
+ \OC_Util::setupFS($userId);
+ }
+
+ 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()), ["app" => $this->appName]);
+ return $error;
+ }
+
+ $url = $this->config->ReplaceDocumentServerUrlToInternal($url);
+
+ $prevVersion = $file->getFileInfo()->getMtime();
+ $fileName = $file->getName();
+ $curExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
+ $downloadExt = $filetype;
+
+ $documentService = new DocumentService($this->trans, $this->config);
+ if ($downloadExt !== $curExt) {
+ $key = DocumentService::GenerateRevisionId($fileId . $url);
+
+ try {
+ $this->logger->debug("Converted from $downloadExt to $curExt", ["app" => $this->appName]);
+ $url = $documentService->GetConvertedUri($url, $downloadExt, $curExt, $key);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "Converted on save error", "app" => $this->appName]);
+ return new JSONResponse(["message" => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ $newData = $documentService->Request($url);
+
+ $prevIsForcesave = KeyManager::wasForcesave($fileId);
+
+ if (RemoteInstance::isRemoteFile($file)) {
+ $isLock = RemoteInstance::lockRemoteKey($file, $isForcesave, null);
+ if ($isForcesave && !$isLock) {
+ break;
+ }
+ } else {
+ KeyManager::lock($fileId, $isForcesave);
+ }
+
+ $this->logger->debug("Track put content " . $file->getPath(), ["app" => $this->appName]);
+ $this->retryOperation(function () use ($file, $newData) {
+ return $file->putContent($newData);
+ });
+
+ if (RemoteInstance::isRemoteFile($file)) {
+ if ($isForcesave) {
+ RemoteInstance::lockRemoteKey($file, false, $isForcesave);
+ }
+ } else {
+ KeyManager::lock($fileId, false);
+ KeyManager::setForcesave($fileId, $isForcesave);
+ }
+
+ if (!$isForcesave
+ && !$prevIsForcesave
+ && $this->versionManager->available
+ && $this->config->GetVersionHistory()) {
+ $changes = null;
+ if (!empty($changesurl)) {
+ $changesurl = $this->config->ReplaceDocumentServerUrlToInternal($changesurl);
+ $changes = $documentService->Request($changesurl);
+ }
+ FileVersions::saveHistory($file->getFileInfo(), $history, $changes, $prevVersion);
+ }
+
+ if (!empty($user) && $this->config->GetVersionHistory()) {
+ FileVersions::saveAuthor($file->getFileInfo(), $user);
+ }
+
+ if ($this->config->checkEncryptionModule() === "master"
+ && !$isForcesave) {
+ KeyManager::delete($fileId);
+ }
+
+ $result = 0;
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "Track: $fileId status $status error", "app" => $this->appName]);
+ }
+ break;
+
+ case self::TrackerStatus_Editing:
+ case self::TrackerStatus_Closed:
+ $result = 0;
+ break;
+ }
+
+ $this->logger->debug("Track: $fileId status $status result $result", ["app" => $this->appName]);
+
+ return new JSONResponse(["error" => $result], Http::STATUS_OK);
+ }
+
+ /**
+ * Getting file by identifier
+ *
+ * @param string $userId - user identifier
+ * @param integer $fileId - file identifier
+ * @param string $filePath - file path
+ * @param integer $version - file version
+ * @param bool $template - file is template
+ *
+ * @return array
+ */
+ private function getFile($userId, $fileId, $filePath = null, $version = 0, $template = false) {
+ if (empty($fileId)) {
+ return [null, new JSONResponse(["message" => $this->trans->t("FileId is empty")], Http::STATUS_BAD_REQUEST)];
+ }
+
+ try {
+ $folder = !$template ? $this->root->getUserFolder($userId) : TemplateManager::GetGlobalTemplateDir();
+ $files = $folder->getById($fileId);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "getFile: $fileId", "app" => $this->appName]);
+ return [null, new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_BAD_REQUEST)];
+ }
+
+ if (empty($files)) {
+ $this->logger->error("Files not found: $fileId", ["app" => $this->appName]);
+ return [null, new JSONResponse(["message" => $this->trans->t("Files not found")], Http::STATUS_NOT_FOUND)];
+ }
+
+ $file = $files[0];
+
+ if (\count($files) > 1 && !empty($filePath)) {
+ $filePath = "/" . $userId . "/files" . $filePath;
+ foreach ($files as $curFile) {
+ if ($curFile->getPath() === $filePath) {
+ $file = $curFile;
+ break;
+ }
+ }
+ }
+
+ if (!($file instanceof File)) {
+ $this->logger->error("File not found: $fileId", ["app" => $this->appName]);
+ return [null, new JSONResponse(["message" => $this->trans->t("File not found")], Http::STATUS_NOT_FOUND)];
+ }
+
+ if ($version > 0 && $this->versionManager->available) {
+ $owner = $file->getFileInfo()->getOwner();
+
+ if ($owner !== null) {
+ if ($owner->getUID() !== $userId) {
+ list($file, $error) = $this->getFile($owner->getUID(), $file->getId());
+
+ if (isset($error)) {
+ return [null, $error];
+ }
+ }
+
+ $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
+
+ if ($version <= \count($versions)) {
+ $fileVersion = array_values($versions)[$version - 1];
+ $file = $this->versionManager->getVersionFile($owner, $file->getFileInfo(), $fileVersion->getRevisionId());
+ }
+ }
+ }
+
+ return [$file, null];
+ }
+
+ /**
+ * Getting file by token
+ *
+ * @param integer $fileId - file identifier
+ * @param string $shareToken - access token
+ * @param integer $version - file version
+ *
+ * @return array
+ */
+ private function getFileByToken($fileId, $shareToken, $version = 0) {
+ list($share, $error) = $this->getShare($shareToken);
+
+ if (isset($error)) {
+ return [null, $error];
+ }
+
+ try {
+ $node = $share->getNode();
+ } catch (NotFoundException $e) {
+ $this->logger->logException($e, ["message" => "getFileByToken error", "app" => $this->appName]);
+ return [null, new JSONResponse(["message" => $this->trans->t("File not found")], Http::STATUS_NOT_FOUND)];
+ }
+
+ if ($node instanceof Folder) {
+ try {
+ $files = $node->getById($fileId);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "getFileByToken: $fileId", "app" => $this->appName]);
+ return [null, new JSONResponse(["message" => $this->trans->t("Invalid request")], Http::STATUS_NOT_FOUND)];
+ }
+
+ if (empty($files)) {
+ return [null, new JSONResponse(["message" => $this->trans->t("File not found")], Http::STATUS_NOT_FOUND)];
+ }
+ $file = $files[0];
+ } else {
+ $file = $node;
+ }
+
+ if ($version > 0 && $this->versionManager->available) {
+ $owner = $file->getFileInfo()->getOwner();
+
+ if ($owner !== null) {
+ $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
+
+ if ($version <= \count($versions)) {
+ $fileVersion = array_values($versions)[$version - 1];
+ $file = $this->versionManager->getVersionFile($owner, $file->getFileInfo(), $fileVersion->getRevisionId());
+ }
+ }
+ }
+
+ return [$file, null];
+ }
+
+ /**
+ * Getting share by token
+ *
+ * @param string $shareToken - access token
+ *
+ * @return array
+ */
+ private function getShare($shareToken) {
+ if (empty($shareToken)) {
+ return [null, new JSONResponse(["message" => $this->trans->t("FileId is empty")], Http::STATUS_BAD_REQUEST)];
+ }
+
+ $share = null;
+ try {
+ $share = $this->shareManager->getShareByToken($shareToken);
+ } catch (ShareNotFound $e) {
+ $this->logger->logException($e, ["message" => "getShare error", "app" => $this->appName]);
+ $share = null;
+ }
+
+ if ($share === null || $share === false) {
+ return [null, new JSONResponse(["message" => $this->trans->t("You do not have enough permissions to view the file")], Http::STATUS_FORBIDDEN)];
+ }
+
+ return [$share, null];
+ }
+
+ /**
+ * Parse user identifier for current instance
+ *
+ * @param string $userId - unique user identifier
+ *
+ * @return string
+ */
+ private function parseUserId($userId) {
+ $instanceId = $this->config->GetSystemValue("instanceid", true);
+ $instanceId = $instanceId . "_";
+
+ if (substr($userId, 0, \strlen($instanceId)) === $instanceId) {
+ return substr($userId, \strlen($instanceId));
+ }
+
+ return $userId;
+ }
+
+ /**
+ * Retry operation if a LockedException occurred
+ * Other exceptions will still be thrown
+ *
+ * @param callable $operation
+ *
+ * @throws LockedException
+ */
+ private function retryOperation(callable $operation) {
+ $i = 0;
+ while (true) {
+ try {
+ return $operation();
+ } catch (LockedException $e) {
+ if (++$i === 4) {
+ throw $e;
+ }
+ }
+ usleep(500000);
+ }
+ }
}
diff --git a/controller/editorapicontroller.php b/controller/editorapicontroller.php
index d1c5851e..bd212e99 100644
--- a/controller/editorapicontroller.php
+++ b/controller/editorapicontroller.php
@@ -49,723 +49,723 @@
* Controller with the main functions
*/
class EditorApiController extends OCSController {
- /**
- * Current user session
- *
- * @var IUserSession
- */
- private $userSession;
-
- /**
- * Root folder
- *
- * @var IRootFolder
- */
- private $root;
-
- /**
- * Url generator service
- *
- * @var IURLGenerator
- */
- private $urlGenerator;
-
- /**
- * l10n service
- *
- * @var IL10N
- */
- private $trans;
-
- /**
- * Logger
- *
- * @var ILogger
- */
- private $logger;
-
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- private $config;
-
- /**
- * Hash generator
- *
- * @var Crypt
- */
- private $crypt;
-
- /**
- * File utility
- *
- * @var FileUtility
- */
- private $fileUtility;
-
- /**
- * File version manager
- *
- * @var VersionManager
- */
- private $versionManager;
-
- /**
- * Tag manager
- *
- * @var ITagManager
- */
- private $tagManager;
-
- /**
- * Mobile regex from https://github.com/ONLYOFFICE/CommunityServer/blob/v9.1.1/web/studio/ASC.Web.Studio/web.appsettings.config#L35
- */
- public const USER_AGENT_MOBILE = "/android|avantgo|playbook|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|symbian|treo|up\\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i";
-
- /**
- * @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 AppConfig $config - application configuration
- * @param Crypt $crypt - hash generator
- * @param IManager $shareManager - Share manager
- * @param ISession $ISession - Session
- * @param ITagManager $tagManager - Tag manager
- */
- public function __construct(
- $AppName,
- IRequest $request,
- IRootFolder $root,
- IUserSession $userSession,
- IURLGenerator $urlGenerator,
- IL10N $trans,
- ILogger $logger,
- AppConfig $config,
- Crypt $crypt,
- IManager $shareManager,
- ISession $session,
- ITagManager $tagManager
- ) {
- parent::__construct($AppName, $request);
-
- $this->userSession = $userSession;
- $this->root = $root;
- $this->urlGenerator = $urlGenerator;
- $this->trans = $trans;
- $this->logger = $logger;
- $this->config = $config;
- $this->crypt = $crypt;
- $this->tagManager = $tagManager;
-
- $this->versionManager = new VersionManager($AppName, $root);
-
- $this->fileUtility = new FileUtility($AppName, $trans, $logger, $config, $shareManager, $session);
- }
-
- /**
- * Filling empty file an template
- *
- * @param int $fileId - file identificator
- *
- * @return JSONResponse
- *
- * @NoAdminRequired
- * @PublicPage
- */
- public function fillempty($fileId) {
- $this->logger->debug("Fill empty: $fileId", ["app" => $this->appName]);
-
- if (empty($fileId)) {
- $this->logger->error("File for filling was not found: $fileId", ["app" => $this->appName]);
- return new JSONResponse(["error" => $this->trans->t("FileId is empty")]);
- }
-
- $userId = $this->userSession->getUser()->getUID();
-
- list($file, $error, $share) = $this->getFile($userId, $fileId);
- if (isset($error)) {
- $this->logger->error("Fill empty: $fileId $error", ["app" => $this->appName]);
- return new JSONResponse(["error" => $error]);
- }
-
- if ($file->getSize() > 0) {
- $this->logger->error("File is't empty: $fileId", ["app" => $this->appName]);
- return new JSONResponse(["error" => $this->trans->t("Not permitted")]);
- }
-
- if (!$file->isUpdateable()) {
- $this->logger->error("File without permission: $fileId", ["app" => $this->appName]);
- return new JSONResponse(["error" => $this->trans->t("Not permitted")]);
- }
-
- $name = $file->getName();
- $template = TemplateManager::GetEmptyTemplate($name);
-
- if (!$template) {
- $this->logger->error("Template for file filling not found: $name ($fileId)", ["app" => $this->appName]);
- return new JSONResponse(["error" => $this->trans->t("Template not found")]);
- }
-
- try {
- $file->putContent($template);
- } catch (NotPermittedException $e) {
- $this->logger->logException($e, ["message" => "Can't put file: $name", "app" => $this->appName]);
- return new JSONResponse(["error" => $this->trans->t("Can't create file")]);
- }
-
- return new JSONResponse([
- ]);
- }
-
- /**
- * Collecting the file parameters for the document service
- *
- * @param integer $fileId - file identifier
- * @param string $filePath - file path
- * @param string $shareToken - access token
- * @param integer $version - file version
- * @param bool $inframe - open in frame
- * @param bool $desktop - desktop label
- * @param bool $template - file is template
- *
- * @return JSONResponse
- *
- * @NoAdminRequired
- * @PublicPage
- * @CORS
- */
- public function config($fileId, $filePath = null, $shareToken = null, $version = 0, $inframe = false, $desktop = false, $template = false, $anchor = null) {
- $user = $this->userSession->getUser();
- $userId = null;
- $accountId = null;
- if (!empty($user)) {
- $userId = $user->getUID();
- $accountId = $user->getAccountId();
- }
-
- list($file, $error, $share) = empty($shareToken) ? $this->getFile($userId, $fileId, $filePath, $template) : $this->fileUtility->getFileByToken($fileId, $shareToken);
-
- if (isset($error)) {
- $this->logger->error("Config: $fileId $error", ["app" => $this->appName]);
- return new JSONResponse(["error" => $error]);
- }
-
- $checkUserAllowGroups = $userId;
- if (!empty($share)) {
- $checkUserAllowGroups = $share->getSharedBy();
- }
- if (!$this->config->isUserAllowedToUse($checkUserAllowGroups)) {
- return new JSONResponse(["error" => $this->trans->t("Not permitted")]);
- }
-
- $fileName = $file->getName();
- $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
- $format = !empty($ext) && \array_key_exists($ext, $this->config->FormatsSetting()) ? $this->config->FormatsSetting()[$ext] : null;
- if (!isset($format)) {
- $this->logger->info("Format is not supported for editing: $fileName", ["app" => $this->appName]);
- return new JSONResponse(["error" => $this->trans->t("Format is not supported")]);
- }
-
- $fileUrl = $this->getUrl($file, $user, $shareToken, $version, null, $template);
-
- $key = null;
- if ($version > 0
- && $this->versionManager->available) {
- $owner = $file->getFileInfo()->getOwner();
- if ($owner !== null) {
- $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
-
- if ($version <= \count($versions)) {
- $fileVersion = array_values($versions)[$version - 1];
-
- $key = $this->fileUtility->getVersionKey($fileVersion);
- }
- }
- }
- if ($key === null) {
- $key = $this->fileUtility->getKey($file, true);
- }
- $key = DocumentService::GenerateRevisionId($key);
-
- $params = [
- "document" => [
- "fileType" => $ext,
- "key" => $key,
- "permissions" => [],
- "title" => $fileName,
- "url" => $fileUrl,
- "referenceData" => [
- "fileKey" => $file->getId(),
- "instanceId" => $this->config->GetSystemValue("instanceid", true),
- ],
- ],
- "documentType" => $format["type"],
- "editorConfig" => [
- "lang" => str_replace("_", "-", \OC::$server->getL10NFactory("")->get("")->getLanguageCode())
- ]
- ];
-
- $restrictedEditing = false;
- $fileStorage = $file->getStorage();
- if (empty($shareToken) && $fileStorage->instanceOfStorage("\OCA\Files_Sharing\SharedStorage")) {
- $storageShare = $fileStorage->getShare();
- if (method_exists($storageShare, "getAttributes")) {
- $attributes = $storageShare->getAttributes();
-
- $permissionsDownload = $attributes->getAttribute("permissions", "download");
- if ($permissionsDownload !== null) {
- $params["document"]["permissions"]["download"] = $params["document"]["permissions"]["print"] = $params["document"]["permissions"]["copy"] = $permissionsDownload === true;
- }
-
- if (isset($format["review"]) && $format["review"]) {
- $permissionsReviewOnly = $attributes->getAttribute($this->appName, "review");
- if ($permissionsReviewOnly !== null && $permissionsReviewOnly === true) {
- $restrictedEditing = true;
- $params["document"]["permissions"]["review"] = true;
- }
- }
-
- if (isset($format["fillForms"]) && $format["fillForms"]) {
- $permissionsFillFormsOnly = $attributes->getAttribute($this->appName, "fillForms");
- if ($permissionsFillFormsOnly !== null && $permissionsFillFormsOnly === true) {
- $restrictedEditing = true;
- $params["document"]["permissions"]["fillForms"] = true;
- }
- }
-
- if (isset($format["comment"]) && $format["comment"]) {
- $permissionsCommentOnly = $attributes->getAttribute($this->appName, "comment");
- if ($permissionsCommentOnly !== null && $permissionsCommentOnly === true) {
- $restrictedEditing = true;
- $params["document"]["permissions"]["comment"] = true;
- }
- }
-
- if (isset($format["modifyFilter"]) && $format["modifyFilter"]) {
- $permissionsModifyFilter = $attributes->getAttribute($this->appName, "modifyFilter");
- if ($permissionsModifyFilter !== null) {
- $params["document"]["permissions"]["modifyFilter"] = $permissionsModifyFilter === true;
- }
- }
- }
- }
-
- $isPersistentLock = false;
- if ($version < 1
- && (\OC::$server->getConfig()->getAppValue("files", "enable_lock_file_action", "no") === "yes")
- && $fileStorage->instanceOfStorage(IPersistentLockingStorage::class)) {
- $locks = $fileStorage->getLocks($file->getFileInfo()->getInternalPath(), false);
- if (\count($locks) > 0) {
- $activeLock = $locks[0];
-
- if ($accountId !== $activeLock->getOwnerAccountId()) {
- $isPersistentLock = true;
- $lockOwner = $activeLock->getOwner();
- $this->logger->debug("File $fileId is locked by $lockOwner", ["app" => $this->appName]);
- }
- }
- }
-
- $canEdit = isset($format["edit"]) && $format["edit"];
- $canFillForms = isset($format["fillForms"]) && $format["fillForms"];
- $editable = $version < 1
- && !$template
- && $file->isUpdateable()
- && !$isPersistentLock
- && (empty($shareToken) || ($share->getPermissions() & Constants::PERMISSION_UPDATE) === Constants::PERMISSION_UPDATE);
- $params["document"]["permissions"]["edit"] = $editable;
- if (($editable || $restrictedEditing) && $canEdit || $canFillForms) {
- $ownerId = null;
- $owner = $file->getOwner();
- if (!empty($owner)) {
- $ownerId = $owner->getUID();
- }
-
- $canProtect = true;
- if ($this->config->GetProtection() === "owner") {
- $canProtect = $ownerId === $userId;
- }
- $params["document"]["permissions"]["protect"] = $canProtect;
-
- if (isset($shareToken)) {
- $params["document"]["permissions"]["chat"] = false;
- $params["document"]["permissions"]["protect"] = false;
- }
-
- $hashCallback = $this->crypt->GetHash(["userId" => $userId, "ownerId" => $ownerId, "fileId" => $file->getId(), "filePath" => $filePath, "shareToken" => $shareToken, "action" => "track"]);
- $callback = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.track", ["doc" => $hashCallback]);
-
- if (!$this->config->UseDemo() && !empty($this->config->GetStorageUrl())) {
- $callback = str_replace($this->urlGenerator->getAbsoluteURL("/"), $this->config->GetStorageUrl(), $callback);
- }
-
- $params["editorConfig"]["callbackUrl"] = $callback;
- } else {
- $params["editorConfig"]["mode"] = "view";
- }
-
- if (\OC::$server->getRequest()->isUserAgent([$this::USER_AGENT_MOBILE])) {
- $params["type"] = "mobile";
- }
-
- if (!$template
- && $file->isUpdateable()
- && !$isPersistentLock
- && (empty($shareToken) || ($share->getPermissions() & Constants::PERMISSION_UPDATE) === Constants::PERMISSION_UPDATE)) {
- $params["document"]["permissions"]["changeHistory"] = true;
- }
-
- if (!empty($userId)) {
- $params["editorConfig"]["user"] = [
- "id" => $this->buildUserId($userId),
- "name" => $user->getDisplayName()
- ];
- }
-
- $folderLink = null;
-
- if (!empty($shareToken)) {
- $node = $share->getNode();
- if ($node instanceof Folder) {
- $sharedFolder = $node;
- $folderPath = $sharedFolder->getRelativePath($file->getParent()->getPath());
- if (!empty($folderPath)) {
- $linkAttr = [
- "path" => $folderPath,
- "scrollto" => $file->getName(),
- "token" => $shareToken
- ];
- $folderLink = $this->urlGenerator->linkToRouteAbsolute("files_sharing.sharecontroller.showShare", $linkAttr);
- }
- }
- } elseif (!empty($userId)) {
- $userFolder = $this->root->getUserFolder($userId);
- $folderPath = $userFolder->getRelativePath($file->getParent()->getPath());
- if (!empty($folderPath)) {
- $linkAttr = [
- "dir" => $folderPath,
- "scrollto" => $file->getName()
- ];
- $folderLink = $this->urlGenerator->linkToRouteAbsolute("files.view.index", $linkAttr);
- }
-
- switch ($params["documentType"]) {
- case "word":
- $createName = $this->trans->t("Document") . ".docx";
- break;
- case "cell":
- $createName = $this->trans->t("Spreadsheet") . ".xlsx";
- break;
- case "slide":
- $createName = $this->trans->t("Presentation") . ".pptx";
- break;
- }
-
- $createParam = [
- "dir" => "/",
- "name" => $createName
- ];
-
- if (!empty($folderPath)) {
- $folder = $userFolder->get($folderPath);
- if (!empty($folder) && $folder->isCreatable()) {
- $createParam["dir"] = $folderPath;
- }
- }
-
- $createUrl = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".editor.create_new", $createParam);
-
- $params["editorConfig"]["createUrl"] = urldecode($createUrl);
-
- $templatesList = TemplateManager::GetGlobalTemplates($file->getMimeType());
- if (!empty($templatesList)) {
- $templates = [];
- foreach ($templatesList as $templateItem) {
- $createParam["templateId"] = $templateItem->getId();
- $createParam["name"] = $templateItem->getName();
-
- array_push($templates, [
- "image" => "",
- "title" => $templateItem->getName(),
- "url" => urldecode($this->urlGenerator->linkToRouteAbsolute($this->appName . ".editor.create_new", $createParam))
- ]);
- }
-
- $params["editorConfig"]["templates"] = $templates;
- }
-
- if (!$template) {
- $params["document"]["info"]["favorite"] = $this->isFavorite($fileId);
- }
- $params["_file_path"] = $userFolder->getRelativePath($file->getPath());
- }
-
- if ($folderLink !== null
- && $this->config->GetSystemValue($this->config->_customization_goback) !== false) {
- $params["editorConfig"]["customization"]["goback"] = [
- "url" => $folderLink
- ];
-
- if (!$desktop) {
- if ($this->config->GetSameTab()) {
- $params["editorConfig"]["customization"]["goback"]["blank"] = false;
- if ($inframe === true) {
- $params["editorConfig"]["customization"]["goback"]["requestClose"] = true;
- }
- }
- }
- }
-
- if ($inframe === true) {
- $params["_files_sharing"] = \OC::$server->getAppManager()->isEnabledForUser("files_sharing");
- }
-
- $params = $this->setCustomization($params);
-
- if ($this->config->UseDemo()) {
- $params["editorConfig"]["tenant"] = $this->config->GetSystemValue("instanceid", true);
- }
-
- if ($anchor !== null) {
- try {
- $actionLink = json_decode($anchor, true);
-
- $params["editorConfig"]["actionLink"] = $actionLink;
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "Config: $fileId decode $anchor", "app" => $this->appName]);
- }
- }
-
- if (!empty($this->config->GetDocumentServerSecret())) {
- $token = \Firebase\JWT\JWT::encode($params, $this->config->GetDocumentServerSecret(), "HS256");
- $params["token"] = $token;
- }
-
- $this->logger->debug("Config is generated for: $fileId ($version) with key $key", ["app" => $this->appName]);
-
- return new JSONResponse($params);
- }
-
- /**
- * Getting file by identifier
- *
- * @param string $userId - user identifier
- * @param integer $fileId - file identifier
- * @param string $filePath - file path
- * @param bool $template - file is template
- *
- * @return array
- */
- private function getFile($userId, $fileId, $filePath = null, $template = false) {
- if (empty($fileId)) {
- return [null, $this->trans->t("FileId is empty"), null];
- }
-
- try {
- $folder = !$template ? $this->root->getUserFolder($userId) : TemplateManager::GetGlobalTemplateDir();
- $files = $folder->getById($fileId);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "getFile: $fileId", "app" => $this->appName]);
- return [null, $this->trans->t("Invalid request"), null];
- }
-
- if (empty($files)) {
- $this->logger->info("Files not found: $fileId", ["app" => $this->appName]);
- return [null, $this->trans->t("File not found"), null];
- }
-
- $file = $files[0];
-
- if (\count($files) > 1 && !empty($filePath)) {
- $filePath = "/" . $userId . "/files" . $filePath;
- foreach ($files as $curFile) {
- if ($curFile->getPath() === $filePath) {
- $file = $curFile;
- break;
- }
- }
- }
-
- if (!$file->isReadable()) {
- return [null, $this->trans->t("You do not have enough permissions to view the file"), null];
- }
-
- return [$file, null, null];
- }
-
- /**
- * Generate secure link to download document
- *
- * @param File $file - file
- * @param IUser $user - user with access
- * @param string $shareToken - access token
- * @param integer $version - file version
- * @param bool $changes - is required url to file changes
- * @param bool $template - file is template
- *
- * @return string
- */
- private function getUrl($file, $user = null, $shareToken = null, $version = 0, $changes = false, $template = false) {
- $data = [
- "action" => "download",
- "fileId" => $file->getId()
- ];
-
- $userId = null;
- if (!empty($user)) {
- $userId = $user->getUID();
- $data["userId"] = $userId;
- }
- if (!empty($shareToken)) {
- $data["shareToken"] = $shareToken;
- }
- if ($version > 0) {
- $data["version"] = $version;
- }
- if ($changes) {
- $data["changes"] = true;
- }
- if ($template) {
- $data["template"] = true;
- }
-
- $hashUrl = $this->crypt->GetHash($data);
-
- $fileUrl = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.download", ["doc" => $hashUrl]);
-
- if (!$this->config->UseDemo() && !empty($this->config->GetStorageUrl())) {
- $fileUrl = str_replace($this->urlGenerator->getAbsoluteURL("/"), $this->config->GetStorageUrl(), $fileUrl);
- }
-
- return $fileUrl;
- }
-
- /**
- * Generate unique user identifier
- *
- * @param string $userId - current user identifier
- *
- * @return string
- */
- private function buildUserId($userId) {
- $instanceId = $this->config->GetSystemValue("instanceid", true);
- $userId = $instanceId . "_" . $userId;
- return $userId;
- }
-
- /**
- * Set customization parameters
- *
- * @param array params - file parameters
- *
- * @return array
- */
- private function setCustomization($params) {
- //default is true
- if ($this->config->GetCustomizationChat() === false) {
- $params["editorConfig"]["customization"]["chat"] = false;
- }
-
- //default is false
- if ($this->config->GetCustomizationCompactHeader() === true) {
- $params["editorConfig"]["customization"]["compactHeader"] = true;
- }
-
- //default is false
- if ($this->config->GetCustomizationFeedback() === true) {
- $params["editorConfig"]["customization"]["feedback"] = true;
- }
-
- //default is false
- if ($this->config->GetCustomizationForcesave() === true) {
- $params["editorConfig"]["customization"]["forcesave"] = true;
- }
-
- //default is true
- if ($this->config->GetCustomizationHelp() === false) {
- $params["editorConfig"]["customization"]["help"] = false;
- }
-
- //default is original
- $reviewDisplay = $this->config->GetCustomizationReviewDisplay();
- if ($reviewDisplay !== "original") {
- $params["editorConfig"]["customization"]["reviewDisplay"] = $reviewDisplay;
- }
-
- $theme = $this->config->GetCustomizationTheme();
- if (isset($theme)) {
- $params["editorConfig"]["customization"]["uiTheme"] = $theme;
- }
-
- //default is false
- if ($this->config->GetCustomizationToolbarNoTabs() === true) {
- $params["editorConfig"]["customization"]["toolbarNoTabs"] = true;
- }
-
- //default is true
- if ($this->config->GetCustomizationMacros() === false) {
- $params["editorConfig"]["customization"]["macros"] = false;
- }
-
- //default is true
- if ($this->config->GetCustomizationPlugins() === false) {
- $params["editorConfig"]["customization"]["plugins"] = false;
- }
-
- /* from system config */
-
- $autosave = $this->config->GetSystemValue($this->config->_customization_autosave);
- if (isset($autosave)) {
- $params["editorConfig"]["customization"]["autosave"] = $autosave;
- }
-
- $customer = $this->config->GetSystemValue($this->config->_customization_customer);
- if (isset($customer)) {
- $params["editorConfig"]["customization"]["customer"] = $customer;
- }
-
- $loaderLogo = $this->config->GetSystemValue($this->config->_customization_loaderLogo);
- if (isset($loaderLogo)) {
- $params["editorConfig"]["customization"]["loaderLogo"] = $loaderLogo;
- }
-
- $loaderName = $this->config->GetSystemValue($this->config->_customization_loaderName);
- if (isset($loaderName)) {
- $params["editorConfig"]["customization"]["loaderName"] = $loaderName;
- }
-
- $logo = $this->config->GetSystemValue($this->config->_customization_logo);
- if (isset($logo)) {
- $params["editorConfig"]["customization"]["logo"] = $logo;
- }
-
- $zoom = $this->config->GetSystemValue($this->config->_customization_zoom);
- if (isset($zoom)) {
- $params["editorConfig"]["customization"]["zoom"] = $zoom;
- }
-
- return $params;
- }
-
- /**
- * Check file favorite
- *
- * @param integer $fileId - file identifier
- *
- * @return bool
- */
- private function isFavorite($fileId) {
- $currentTags = $this->tagManager->load("files")->getTagsForObjects([$fileId]);
- if ($currentTags) {
- return \in_array(Tags::TAG_FAVORITE, $currentTags[$fileId]);
- }
-
- return false;
- }
+ /**
+ * Current user session
+ *
+ * @var IUserSession
+ */
+ private $userSession;
+
+ /**
+ * Root folder
+ *
+ * @var IRootFolder
+ */
+ private $root;
+
+ /**
+ * Url generator service
+ *
+ * @var IURLGenerator
+ */
+ private $urlGenerator;
+
+ /**
+ * l10n service
+ *
+ * @var IL10N
+ */
+ private $trans;
+
+ /**
+ * Logger
+ *
+ * @var ILogger
+ */
+ private $logger;
+
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ private $config;
+
+ /**
+ * Hash generator
+ *
+ * @var Crypt
+ */
+ private $crypt;
+
+ /**
+ * File utility
+ *
+ * @var FileUtility
+ */
+ private $fileUtility;
+
+ /**
+ * File version manager
+ *
+ * @var VersionManager
+ */
+ private $versionManager;
+
+ /**
+ * Tag manager
+ *
+ * @var ITagManager
+ */
+ private $tagManager;
+
+ /**
+ * Mobile regex from https://github.com/ONLYOFFICE/CommunityServer/blob/v9.1.1/web/studio/ASC.Web.Studio/web.appsettings.config#L35
+ */
+ public const USER_AGENT_MOBILE = "/android|avantgo|playbook|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|symbian|treo|up\\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i";
+
+ /**
+ * @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 AppConfig $config - application configuration
+ * @param Crypt $crypt - hash generator
+ * @param IManager $shareManager - Share manager
+ * @param ISession $ISession - Session
+ * @param ITagManager $tagManager - Tag manager
+ */
+ public function __construct(
+ $AppName,
+ IRequest $request,
+ IRootFolder $root,
+ IUserSession $userSession,
+ IURLGenerator $urlGenerator,
+ IL10N $trans,
+ ILogger $logger,
+ AppConfig $config,
+ Crypt $crypt,
+ IManager $shareManager,
+ ISession $session,
+ ITagManager $tagManager
+ ) {
+ parent::__construct($AppName, $request);
+
+ $this->userSession = $userSession;
+ $this->root = $root;
+ $this->urlGenerator = $urlGenerator;
+ $this->trans = $trans;
+ $this->logger = $logger;
+ $this->config = $config;
+ $this->crypt = $crypt;
+ $this->tagManager = $tagManager;
+
+ $this->versionManager = new VersionManager($AppName, $root);
+
+ $this->fileUtility = new FileUtility($AppName, $trans, $logger, $config, $shareManager, $session);
+ }
+
+ /**
+ * Filling empty file an template
+ *
+ * @param int $fileId - file identificator
+ *
+ * @return JSONResponse
+ *
+ * @NoAdminRequired
+ * @PublicPage
+ */
+ public function fillempty($fileId) {
+ $this->logger->debug("Fill empty: $fileId", ["app" => $this->appName]);
+
+ if (empty($fileId)) {
+ $this->logger->error("File for filling was not found: $fileId", ["app" => $this->appName]);
+ return new JSONResponse(["error" => $this->trans->t("FileId is empty")]);
+ }
+
+ $userId = $this->userSession->getUser()->getUID();
+
+ list($file, $error, $share) = $this->getFile($userId, $fileId);
+ if (isset($error)) {
+ $this->logger->error("Fill empty: $fileId $error", ["app" => $this->appName]);
+ return new JSONResponse(["error" => $error]);
+ }
+
+ if ($file->getSize() > 0) {
+ $this->logger->error("File is't empty: $fileId", ["app" => $this->appName]);
+ return new JSONResponse(["error" => $this->trans->t("Not permitted")]);
+ }
+
+ if (!$file->isUpdateable()) {
+ $this->logger->error("File without permission: $fileId", ["app" => $this->appName]);
+ return new JSONResponse(["error" => $this->trans->t("Not permitted")]);
+ }
+
+ $name = $file->getName();
+ $template = TemplateManager::GetEmptyTemplate($name);
+
+ if (!$template) {
+ $this->logger->error("Template for file filling not found: $name ($fileId)", ["app" => $this->appName]);
+ return new JSONResponse(["error" => $this->trans->t("Template not found")]);
+ }
+
+ try {
+ $file->putContent($template);
+ } catch (NotPermittedException $e) {
+ $this->logger->logException($e, ["message" => "Can't put file: $name", "app" => $this->appName]);
+ return new JSONResponse(["error" => $this->trans->t("Can't create file")]);
+ }
+
+ return new JSONResponse([
+ ]);
+ }
+
+ /**
+ * Collecting the file parameters for the document service
+ *
+ * @param integer $fileId - file identifier
+ * @param string $filePath - file path
+ * @param string $shareToken - access token
+ * @param integer $version - file version
+ * @param bool $inframe - open in frame
+ * @param bool $desktop - desktop label
+ * @param bool $template - file is template
+ *
+ * @return JSONResponse
+ *
+ * @NoAdminRequired
+ * @PublicPage
+ * @CORS
+ */
+ public function config($fileId, $filePath = null, $shareToken = null, $version = 0, $inframe = false, $desktop = false, $template = false, $anchor = null) {
+ $user = $this->userSession->getUser();
+ $userId = null;
+ $accountId = null;
+ if (!empty($user)) {
+ $userId = $user->getUID();
+ $accountId = $user->getAccountId();
+ }
+
+ list($file, $error, $share) = empty($shareToken) ? $this->getFile($userId, $fileId, $filePath, $template) : $this->fileUtility->getFileByToken($fileId, $shareToken);
+
+ if (isset($error)) {
+ $this->logger->error("Config: $fileId $error", ["app" => $this->appName]);
+ return new JSONResponse(["error" => $error]);
+ }
+
+ $checkUserAllowGroups = $userId;
+ if (!empty($share)) {
+ $checkUserAllowGroups = $share->getSharedBy();
+ }
+ if (!$this->config->isUserAllowedToUse($checkUserAllowGroups)) {
+ return new JSONResponse(["error" => $this->trans->t("Not permitted")]);
+ }
+
+ $fileName = $file->getName();
+ $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
+ $format = !empty($ext) && \array_key_exists($ext, $this->config->FormatsSetting()) ? $this->config->FormatsSetting()[$ext] : null;
+ if (!isset($format)) {
+ $this->logger->info("Format is not supported for editing: $fileName", ["app" => $this->appName]);
+ return new JSONResponse(["error" => $this->trans->t("Format is not supported")]);
+ }
+
+ $fileUrl = $this->getUrl($file, $user, $shareToken, $version, null, $template);
+
+ $key = null;
+ if ($version > 0
+ && $this->versionManager->available) {
+ $owner = $file->getFileInfo()->getOwner();
+ if ($owner !== null) {
+ $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
+
+ if ($version <= \count($versions)) {
+ $fileVersion = array_values($versions)[$version - 1];
+
+ $key = $this->fileUtility->getVersionKey($fileVersion);
+ }
+ }
+ }
+ if ($key === null) {
+ $key = $this->fileUtility->getKey($file, true);
+ }
+ $key = DocumentService::GenerateRevisionId($key);
+
+ $params = [
+ "document" => [
+ "fileType" => $ext,
+ "key" => $key,
+ "permissions" => [],
+ "title" => $fileName,
+ "url" => $fileUrl,
+ "referenceData" => [
+ "fileKey" => $file->getId(),
+ "instanceId" => $this->config->GetSystemValue("instanceid", true),
+ ],
+ ],
+ "documentType" => $format["type"],
+ "editorConfig" => [
+ "lang" => str_replace("_", "-", \OC::$server->getL10NFactory("")->get("")->getLanguageCode())
+ ]
+ ];
+
+ $restrictedEditing = false;
+ $fileStorage = $file->getStorage();
+ if (empty($shareToken) && $fileStorage->instanceOfStorage("\OCA\Files_Sharing\SharedStorage")) {
+ $storageShare = $fileStorage->getShare();
+ if (method_exists($storageShare, "getAttributes")) {
+ $attributes = $storageShare->getAttributes();
+
+ $permissionsDownload = $attributes->getAttribute("permissions", "download");
+ if ($permissionsDownload !== null) {
+ $params["document"]["permissions"]["download"] = $params["document"]["permissions"]["print"] = $params["document"]["permissions"]["copy"] = $permissionsDownload === true;
+ }
+
+ if (isset($format["review"]) && $format["review"]) {
+ $permissionsReviewOnly = $attributes->getAttribute($this->appName, "review");
+ if ($permissionsReviewOnly !== null && $permissionsReviewOnly === true) {
+ $restrictedEditing = true;
+ $params["document"]["permissions"]["review"] = true;
+ }
+ }
+
+ if (isset($format["fillForms"]) && $format["fillForms"]) {
+ $permissionsFillFormsOnly = $attributes->getAttribute($this->appName, "fillForms");
+ if ($permissionsFillFormsOnly !== null && $permissionsFillFormsOnly === true) {
+ $restrictedEditing = true;
+ $params["document"]["permissions"]["fillForms"] = true;
+ }
+ }
+
+ if (isset($format["comment"]) && $format["comment"]) {
+ $permissionsCommentOnly = $attributes->getAttribute($this->appName, "comment");
+ if ($permissionsCommentOnly !== null && $permissionsCommentOnly === true) {
+ $restrictedEditing = true;
+ $params["document"]["permissions"]["comment"] = true;
+ }
+ }
+
+ if (isset($format["modifyFilter"]) && $format["modifyFilter"]) {
+ $permissionsModifyFilter = $attributes->getAttribute($this->appName, "modifyFilter");
+ if ($permissionsModifyFilter !== null) {
+ $params["document"]["permissions"]["modifyFilter"] = $permissionsModifyFilter === true;
+ }
+ }
+ }
+ }
+
+ $isPersistentLock = false;
+ if ($version < 1
+ && (\OC::$server->getConfig()->getAppValue("files", "enable_lock_file_action", "no") === "yes")
+ && $fileStorage->instanceOfStorage(IPersistentLockingStorage::class)) {
+ $locks = $fileStorage->getLocks($file->getFileInfo()->getInternalPath(), false);
+ if (\count($locks) > 0) {
+ $activeLock = $locks[0];
+
+ if ($accountId !== $activeLock->getOwnerAccountId()) {
+ $isPersistentLock = true;
+ $lockOwner = $activeLock->getOwner();
+ $this->logger->debug("File $fileId is locked by $lockOwner", ["app" => $this->appName]);
+ }
+ }
+ }
+
+ $canEdit = isset($format["edit"]) && $format["edit"];
+ $canFillForms = isset($format["fillForms"]) && $format["fillForms"];
+ $editable = $version < 1
+ && !$template
+ && $file->isUpdateable()
+ && !$isPersistentLock
+ && (empty($shareToken) || ($share->getPermissions() & Constants::PERMISSION_UPDATE) === Constants::PERMISSION_UPDATE);
+ $params["document"]["permissions"]["edit"] = $editable;
+ if (($editable || $restrictedEditing) && $canEdit || $canFillForms) {
+ $ownerId = null;
+ $owner = $file->getOwner();
+ if (!empty($owner)) {
+ $ownerId = $owner->getUID();
+ }
+
+ $canProtect = true;
+ if ($this->config->GetProtection() === "owner") {
+ $canProtect = $ownerId === $userId;
+ }
+ $params["document"]["permissions"]["protect"] = $canProtect;
+
+ if (isset($shareToken)) {
+ $params["document"]["permissions"]["chat"] = false;
+ $params["document"]["permissions"]["protect"] = false;
+ }
+
+ $hashCallback = $this->crypt->GetHash(["userId" => $userId, "ownerId" => $ownerId, "fileId" => $file->getId(), "filePath" => $filePath, "shareToken" => $shareToken, "action" => "track"]);
+ $callback = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.track", ["doc" => $hashCallback]);
+
+ if (!$this->config->UseDemo() && !empty($this->config->GetStorageUrl())) {
+ $callback = str_replace($this->urlGenerator->getAbsoluteURL("/"), $this->config->GetStorageUrl(), $callback);
+ }
+
+ $params["editorConfig"]["callbackUrl"] = $callback;
+ } else {
+ $params["editorConfig"]["mode"] = "view";
+ }
+
+ if (\OC::$server->getRequest()->isUserAgent([$this::USER_AGENT_MOBILE])) {
+ $params["type"] = "mobile";
+ }
+
+ if (!$template
+ && $file->isUpdateable()
+ && !$isPersistentLock
+ && (empty($shareToken) || ($share->getPermissions() & Constants::PERMISSION_UPDATE) === Constants::PERMISSION_UPDATE)) {
+ $params["document"]["permissions"]["changeHistory"] = true;
+ }
+
+ if (!empty($userId)) {
+ $params["editorConfig"]["user"] = [
+ "id" => $this->buildUserId($userId),
+ "name" => $user->getDisplayName()
+ ];
+ }
+
+ $folderLink = null;
+
+ if (!empty($shareToken)) {
+ $node = $share->getNode();
+ if ($node instanceof Folder) {
+ $sharedFolder = $node;
+ $folderPath = $sharedFolder->getRelativePath($file->getParent()->getPath());
+ if (!empty($folderPath)) {
+ $linkAttr = [
+ "path" => $folderPath,
+ "scrollto" => $file->getName(),
+ "token" => $shareToken
+ ];
+ $folderLink = $this->urlGenerator->linkToRouteAbsolute("files_sharing.sharecontroller.showShare", $linkAttr);
+ }
+ }
+ } elseif (!empty($userId)) {
+ $userFolder = $this->root->getUserFolder($userId);
+ $folderPath = $userFolder->getRelativePath($file->getParent()->getPath());
+ if (!empty($folderPath)) {
+ $linkAttr = [
+ "dir" => $folderPath,
+ "scrollto" => $file->getName()
+ ];
+ $folderLink = $this->urlGenerator->linkToRouteAbsolute("files.view.index", $linkAttr);
+ }
+
+ switch ($params["documentType"]) {
+ case "word":
+ $createName = $this->trans->t("Document") . ".docx";
+ break;
+ case "cell":
+ $createName = $this->trans->t("Spreadsheet") . ".xlsx";
+ break;
+ case "slide":
+ $createName = $this->trans->t("Presentation") . ".pptx";
+ break;
+ }
+
+ $createParam = [
+ "dir" => "/",
+ "name" => $createName
+ ];
+
+ if (!empty($folderPath)) {
+ $folder = $userFolder->get($folderPath);
+ if (!empty($folder) && $folder->isCreatable()) {
+ $createParam["dir"] = $folderPath;
+ }
+ }
+
+ $createUrl = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".editor.create_new", $createParam);
+
+ $params["editorConfig"]["createUrl"] = urldecode($createUrl);
+
+ $templatesList = TemplateManager::GetGlobalTemplates($file->getMimeType());
+ if (!empty($templatesList)) {
+ $templates = [];
+ foreach ($templatesList as $templateItem) {
+ $createParam["templateId"] = $templateItem->getId();
+ $createParam["name"] = $templateItem->getName();
+
+ array_push($templates, [
+ "image" => "",
+ "title" => $templateItem->getName(),
+ "url" => urldecode($this->urlGenerator->linkToRouteAbsolute($this->appName . ".editor.create_new", $createParam))
+ ]);
+ }
+
+ $params["editorConfig"]["templates"] = $templates;
+ }
+
+ if (!$template) {
+ $params["document"]["info"]["favorite"] = $this->isFavorite($fileId);
+ }
+ $params["_file_path"] = $userFolder->getRelativePath($file->getPath());
+ }
+
+ if ($folderLink !== null
+ && $this->config->GetSystemValue($this->config->_customization_goback) !== false) {
+ $params["editorConfig"]["customization"]["goback"] = [
+ "url" => $folderLink
+ ];
+
+ if (!$desktop) {
+ if ($this->config->GetSameTab()) {
+ $params["editorConfig"]["customization"]["goback"]["blank"] = false;
+ if ($inframe === true) {
+ $params["editorConfig"]["customization"]["goback"]["requestClose"] = true;
+ }
+ }
+ }
+ }
+
+ if ($inframe === true) {
+ $params["_files_sharing"] = \OC::$server->getAppManager()->isEnabledForUser("files_sharing");
+ }
+
+ $params = $this->setCustomization($params);
+
+ if ($this->config->UseDemo()) {
+ $params["editorConfig"]["tenant"] = $this->config->GetSystemValue("instanceid", true);
+ }
+
+ if ($anchor !== null) {
+ try {
+ $actionLink = json_decode($anchor, true);
+
+ $params["editorConfig"]["actionLink"] = $actionLink;
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "Config: $fileId decode $anchor", "app" => $this->appName]);
+ }
+ }
+
+ if (!empty($this->config->GetDocumentServerSecret())) {
+ $token = \Firebase\JWT\JWT::encode($params, $this->config->GetDocumentServerSecret(), "HS256");
+ $params["token"] = $token;
+ }
+
+ $this->logger->debug("Config is generated for: $fileId ($version) with key $key", ["app" => $this->appName]);
+
+ return new JSONResponse($params);
+ }
+
+ /**
+ * Getting file by identifier
+ *
+ * @param string $userId - user identifier
+ * @param integer $fileId - file identifier
+ * @param string $filePath - file path
+ * @param bool $template - file is template
+ *
+ * @return array
+ */
+ private function getFile($userId, $fileId, $filePath = null, $template = false) {
+ if (empty($fileId)) {
+ return [null, $this->trans->t("FileId is empty"), null];
+ }
+
+ try {
+ $folder = !$template ? $this->root->getUserFolder($userId) : TemplateManager::GetGlobalTemplateDir();
+ $files = $folder->getById($fileId);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "getFile: $fileId", "app" => $this->appName]);
+ return [null, $this->trans->t("Invalid request"), null];
+ }
+
+ if (empty($files)) {
+ $this->logger->info("Files not found: $fileId", ["app" => $this->appName]);
+ return [null, $this->trans->t("File not found"), null];
+ }
+
+ $file = $files[0];
+
+ if (\count($files) > 1 && !empty($filePath)) {
+ $filePath = "/" . $userId . "/files" . $filePath;
+ foreach ($files as $curFile) {
+ if ($curFile->getPath() === $filePath) {
+ $file = $curFile;
+ break;
+ }
+ }
+ }
+
+ if (!$file->isReadable()) {
+ return [null, $this->trans->t("You do not have enough permissions to view the file"), null];
+ }
+
+ return [$file, null, null];
+ }
+
+ /**
+ * Generate secure link to download document
+ *
+ * @param File $file - file
+ * @param IUser $user - user with access
+ * @param string $shareToken - access token
+ * @param integer $version - file version
+ * @param bool $changes - is required url to file changes
+ * @param bool $template - file is template
+ *
+ * @return string
+ */
+ private function getUrl($file, $user = null, $shareToken = null, $version = 0, $changes = false, $template = false) {
+ $data = [
+ "action" => "download",
+ "fileId" => $file->getId()
+ ];
+
+ $userId = null;
+ if (!empty($user)) {
+ $userId = $user->getUID();
+ $data["userId"] = $userId;
+ }
+ if (!empty($shareToken)) {
+ $data["shareToken"] = $shareToken;
+ }
+ if ($version > 0) {
+ $data["version"] = $version;
+ }
+ if ($changes) {
+ $data["changes"] = true;
+ }
+ if ($template) {
+ $data["template"] = true;
+ }
+
+ $hashUrl = $this->crypt->GetHash($data);
+
+ $fileUrl = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.download", ["doc" => $hashUrl]);
+
+ if (!$this->config->UseDemo() && !empty($this->config->GetStorageUrl())) {
+ $fileUrl = str_replace($this->urlGenerator->getAbsoluteURL("/"), $this->config->GetStorageUrl(), $fileUrl);
+ }
+
+ return $fileUrl;
+ }
+
+ /**
+ * Generate unique user identifier
+ *
+ * @param string $userId - current user identifier
+ *
+ * @return string
+ */
+ private function buildUserId($userId) {
+ $instanceId = $this->config->GetSystemValue("instanceid", true);
+ $userId = $instanceId . "_" . $userId;
+ return $userId;
+ }
+
+ /**
+ * Set customization parameters
+ *
+ * @param array params - file parameters
+ *
+ * @return array
+ */
+ private function setCustomization($params) {
+ //default is true
+ if ($this->config->GetCustomizationChat() === false) {
+ $params["editorConfig"]["customization"]["chat"] = false;
+ }
+
+ //default is false
+ if ($this->config->GetCustomizationCompactHeader() === true) {
+ $params["editorConfig"]["customization"]["compactHeader"] = true;
+ }
+
+ //default is false
+ if ($this->config->GetCustomizationFeedback() === true) {
+ $params["editorConfig"]["customization"]["feedback"] = true;
+ }
+
+ //default is false
+ if ($this->config->GetCustomizationForcesave() === true) {
+ $params["editorConfig"]["customization"]["forcesave"] = true;
+ }
+
+ //default is true
+ if ($this->config->GetCustomizationHelp() === false) {
+ $params["editorConfig"]["customization"]["help"] = false;
+ }
+
+ //default is original
+ $reviewDisplay = $this->config->GetCustomizationReviewDisplay();
+ if ($reviewDisplay !== "original") {
+ $params["editorConfig"]["customization"]["reviewDisplay"] = $reviewDisplay;
+ }
+
+ $theme = $this->config->GetCustomizationTheme();
+ if (isset($theme)) {
+ $params["editorConfig"]["customization"]["uiTheme"] = $theme;
+ }
+
+ //default is false
+ if ($this->config->GetCustomizationToolbarNoTabs() === true) {
+ $params["editorConfig"]["customization"]["toolbarNoTabs"] = true;
+ }
+
+ //default is true
+ if ($this->config->GetCustomizationMacros() === false) {
+ $params["editorConfig"]["customization"]["macros"] = false;
+ }
+
+ //default is true
+ if ($this->config->GetCustomizationPlugins() === false) {
+ $params["editorConfig"]["customization"]["plugins"] = false;
+ }
+
+ /* from system config */
+
+ $autosave = $this->config->GetSystemValue($this->config->_customization_autosave);
+ if (isset($autosave)) {
+ $params["editorConfig"]["customization"]["autosave"] = $autosave;
+ }
+
+ $customer = $this->config->GetSystemValue($this->config->_customization_customer);
+ if (isset($customer)) {
+ $params["editorConfig"]["customization"]["customer"] = $customer;
+ }
+
+ $loaderLogo = $this->config->GetSystemValue($this->config->_customization_loaderLogo);
+ if (isset($loaderLogo)) {
+ $params["editorConfig"]["customization"]["loaderLogo"] = $loaderLogo;
+ }
+
+ $loaderName = $this->config->GetSystemValue($this->config->_customization_loaderName);
+ if (isset($loaderName)) {
+ $params["editorConfig"]["customization"]["loaderName"] = $loaderName;
+ }
+
+ $logo = $this->config->GetSystemValue($this->config->_customization_logo);
+ if (isset($logo)) {
+ $params["editorConfig"]["customization"]["logo"] = $logo;
+ }
+
+ $zoom = $this->config->GetSystemValue($this->config->_customization_zoom);
+ if (isset($zoom)) {
+ $params["editorConfig"]["customization"]["zoom"] = $zoom;
+ }
+
+ return $params;
+ }
+
+ /**
+ * Check file favorite
+ *
+ * @param integer $fileId - file identifier
+ *
+ * @return bool
+ */
+ private function isFavorite($fileId) {
+ $currentTags = $this->tagManager->load("files")->getTagsForObjects([$fileId]);
+ if ($currentTags) {
+ return \in_array(Tags::TAG_FAVORITE, $currentTags[$fileId]);
+ }
+
+ return false;
+ }
}
diff --git a/controller/editorcontroller.php b/controller/editorcontroller.php
index 7e32f805..20cfcac4 100644
--- a/controller/editorcontroller.php
+++ b/controller/editorcontroller.php
@@ -55,1406 +55,1406 @@
* Controller with the main functions
*/
class EditorController extends Controller {
- /**
- * Current user session
- *
- * @var IUserSession
- */
- private $userSession;
-
- /**
- * Current user manager
- *
- * @var IUserManager
- */
- private $userManager;
-
- /**
- * Root folder
- *
- * @var IRootFolder
- */
- private $root;
-
- /**
- * Url generator service
- *
- * @var IURLGenerator
- */
- private $urlGenerator;
-
- /**
- * l10n service
- *
- * @var IL10N
- */
- private $trans;
-
- /**
- * Logger
- *
- * @var ILogger
- */
- private $logger;
-
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- private $config;
-
- /**
- * Hash generator
- *
- * @var Crypt
- */
- private $crypt;
-
- /**
- * File utility
- *
- * @var FileUtility
- */
- private $fileUtility;
-
- /**
- * File version manager
- *
- * @var VersionManager
- */
- private $versionManager;
-
- /**
- * Share manager
- *
- * @var IManager
- */
- private $shareManager;
-
- /**
- * Group manager
- *
- * @var IGroupManager
- */
- private $groupManager;
-
- /**
- * @param string $AppName - application name
- * @param IRequest $request - request object
- * @param IRootFolder $root - root folder
- * @param IUserSession $userSession - current user session
- * @param IUserManager $userManager - current user manager
- * @param IURLGenerator $urlGenerator - url generator service
- * @param IL10N $trans - l10n service
- * @param ILogger $logger - logger
- * @param AppConfig $config - application configuration
- * @param Crypt $crypt - hash generator
- * @param IManager $shareManager - Share manager
- * @param ISession $session - Session
- * @param IGroupManager $groupManager - Group manager
- */
- public function __construct(
- $AppName,
- IRequest $request,
- IRootFolder $root,
- IUserSession $userSession,
- IUserManager $userManager,
- IURLGenerator $urlGenerator,
- IL10N $trans,
- ILogger $logger,
- AppConfig $config,
- Crypt $crypt,
- IManager $shareManager,
- ISession $session,
- IGroupManager $groupManager
- ) {
- parent::__construct($AppName, $request);
-
- $this->userSession = $userSession;
- $this->userManager = $userManager;
- $this->root = $root;
- $this->urlGenerator = $urlGenerator;
- $this->trans = $trans;
- $this->logger = $logger;
- $this->config = $config;
- $this->crypt = $crypt;
- $this->shareManager = $shareManager;
- $this->groupManager = $groupManager;
-
- $this->versionManager = new VersionManager($AppName, $root);
-
- $this->fileUtility = new FileUtility($AppName, $trans, $logger, $config, $shareManager, $session);
- }
-
- /**
- * Create new file in folder
- *
- * @param string $name - file name
- * @param string $dir - folder path
- * @param string $templateId - file identifier
- * @param string $targetPath - file path for using as template for create
- * @param string $shareToken - access token
- *
- * @return array
- *
- * @NoAdminRequired
- * @PublicPage
- */
- public function create($name, $dir, $templateId = null, $targetPath = null, $shareToken = null) {
- $this->logger->debug("Create: $name", ["app" => $this->appName]);
-
- if (empty($shareToken) && !$this->config->isUserAllowedToUse()) {
- return ["error" => $this->trans->t("Not permitted")];
- }
-
- if (empty($name)) {
- $this->logger->error("File name for creation was not found: $name", ["app" => $this->appName]);
- return ["error" => $this->trans->t("Template not found")];
- }
-
- $user = null;
- if (empty($shareToken)) {
- $user = $this->userSession->getUser();
- $userId = $user->getUID();
- $userFolder = $this->root->getUserFolder($userId);
- } else {
- list($userFolder, $error, $share) = $this->fileUtility->getNodeByToken($shareToken);
-
- if (isset($error)) {
- $this->logger->error("Create: $error", ["app" => $this->appName]);
- return ["error" => $error];
- }
-
- if ($userFolder instanceof File) {
- return ["error" => $this->trans->t("You don't have enough permission to create")];
- }
-
- if (!empty($shareToken) && ($share->getPermissions() & Constants::PERMISSION_CREATE) === 0) {
- $this->logger->error("Create in public folder without access", ["app" => $this->appName]);
- return ["error" => $this->trans->t("You do not have enough permissions to view the file")];
- }
- }
-
- $folder = $userFolder->get($dir);
-
- if ($folder === null) {
- $this->logger->error("Folder for file creation was not found: $dir", ["app" => $this->appName]);
- return ["error" => $this->trans->t("The required folder was not found")];
- }
- if (!($folder->isCreatable() && $folder->isUpdateable())) {
- $this->logger->error("Folder for file creation without permission: $dir", ["app" => $this->appName]);
- return ["error" => $this->trans->t("You don't have enough permission to create")];
- }
-
- if (!empty($templateId)) {
- $templateFile = TemplateManager::GetTemplate($templateId);
- if ($templateFile) {
- $template = $templateFile->getContent();
- }
- } elseif (!empty($targetPath)) {
- $targetFile = $userFolder->get($targetPath);
-
- $canDownload = $this->fileUtility->hasPermissionAttribute($targetFile);
- if (!$canDownload) {
- return ["error" => $this->trans->t("Not permitted")];
- }
-
- $targetId = $targetFile->getId();
- $targetName = $targetFile->getName();
- $targetExt = strtolower(pathinfo($targetName, PATHINFO_EXTENSION));
- $targetKey = $this->fileUtility->getKey($targetFile);
-
- $fileUrl = $this->getUrl($targetFile, $user, $shareToken);
-
- $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
- $documentService = new DocumentService($this->trans, $this->config);
- try {
- $newFileUri = $documentService->GetConvertedUri($fileUrl, $targetExt, $ext, $targetKey);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "GetConvertedUri: " . $targetFile->getId(), "app" => $this->appName]);
- return ["error" => $e->getMessage()];
- }
- $template = $documentService->Request($newFileUri);
- } else {
- $template = TemplateManager::GetEmptyTemplate($name);
- }
-
- if (!$template) {
- $this->logger->error("Template for file creation not found: $name ($templateId)", ["app" => $this->appName]);
- return ["error" => $this->trans->t("Template not found")];
- }
-
- $name = $folder->getNonExistingName($name);
-
- try {
- $file = $folder->newFile($name);
-
- $file->putContent($template);
- } catch (NotPermittedException $e) {
- $this->logger->logException($e, ["message" => "Can't create file: $name", "app" => $this->appName]);
- return ["error" => $this->trans->t("Can't create file")];
- } catch (ForbiddenException $e) {
- $this->logger->logException($e, ["message" => "Can't put file: $name", "app" => $this->appName]);
- return ["error" => $this->trans->t("Can't create file")];
- }
-
- $fileInfo = $file->getFileInfo();
-
- $result = Helper::formatFileInfo($fileInfo);
- return $result;
- }
-
- /**
- * Create new file in folder from editor
- *
- * @param string $name - file name
- * @param string $dir - folder path
- * @param string $templateId - file identifier
- *
- * @return TemplateResponse|RedirectResponse
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- */
- public function createNew($name, $dir, $templateId = null) {
- $this->logger->debug("Create from editor: $name in $dir", ["app" => $this->appName]);
-
- $result = $this->create($name, $dir, $templateId);
- if (isset($result["error"])) {
- return $this->renderError($result["error"]);
- }
-
- $openEditor = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".editor.index", ["fileId" => $result["id"]]);
- return new RedirectResponse($openEditor);
- }
-
- /**
- * Get users
- *
- * @param $fileId - file identifier
- *
- * @return array
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- */
- public function users($fileId) {
- $this->logger->debug("Search users", ["app" => $this->appName]);
- $result = [];
-
- if (!$this->config->isUserAllowedToUse()) {
- return $result;
- }
-
- if (!$this->allowEnumeration()) {
- return $result;
- }
-
- $autocompleteMemberGroup = false;
- if ($this->limitEnumerationToGroups()) {
- $autocompleteMemberGroup = true;
- }
-
- $currentUser = $this->userSession->getUser();
- $currentUserId = $currentUser->getUID();
-
- list($file, $error, $share) = $this->getFile($currentUserId, $fileId);
- if (isset($error)) {
- $this->logger->error("Users: $fileId $error", ["app" => $this->appName]);
- return $result;
- }
-
- $canShare = (($file->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE);
-
- $shareMemberGroups = $this->shareManager->shareWithGroupMembersOnly();
-
- $all = false;
- $users = [];
- if ($canShare) {
- if ($shareMemberGroups || $autocompleteMemberGroup) {
- $currentUserGroups = $this->groupManager->getUserGroupIds($currentUser);
- foreach ($currentUserGroups as $currentUserGroup) {
- $group = $this->groupManager->get($currentUserGroup);
- foreach ($group->getUsers() as $user) {
- if (!\in_array($user, $users)) {
- array_push($users, $user);
- }
- }
- }
- } else {
- $users = $this->userManager->search("");
- $all = true;
- }
- }
-
- if (!$all) {
- $accessList = $this->getAccessList($file);
- foreach ($accessList as $accessUser) {
- if (!\in_array($accessUser, $users)) {
- array_push($users, $accessUser);
- }
- }
- }
-
- foreach ($users as $user) {
- $email = $user->getEMailAddress();
- if ($user->getUID() != $currentUserId && !empty($email)) {
- array_push($result, [
- "email" => $email,
- "name" => $user->getDisplayName()
- ]);
- }
- }
-
- return $result;
- }
-
- /**
- * Send notify about mention
- *
- * @param int $fileId - file identifier
- * @param string $anchor - the anchor on target content
- * @param string $comment - comment
- * @param array $emails - emails array to whom to send notify
- *
- * @return array
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- */
- public function mention($fileId, $anchor, $comment, $emails) {
- $this->logger->debug("mention: from $fileId to " . json_encode($emails), ["app" => $this->appName]);
-
- if (!$this->config->isUserAllowedToUse()) {
- return ["error" => $this->trans->t("Not permitted")];
- }
-
- if (empty($emails)) {
- return ["error" => $this->trans->t("Failed to send notification")];
- }
-
- $recipientIds = [];
- foreach ($emails as $email) {
- $recipients = $this->userManager->getByEmail($email);
- foreach ($recipients as $recipient) {
- $recipientId = $recipient->getUID();
- if (!\in_array($recipientId, $recipientIds)) {
- array_push($recipientIds, $recipientId);
- }
- }
- }
-
- $user = $this->userSession->getUser();
- $userId = null;
- if (!empty($user)) {
- $userId = $user->getUID();
- }
-
- list($file, $error, $share) = $this->getFile($userId, $fileId);
- if (isset($error)) {
- $this->logger->error("Mention: $fileId $error", ["app" => $this->appName]);
- return ["error" => $this->trans->t("Failed to send notification")];
- }
-
- foreach ($emails as $email) {
- $substrToDelete = "+" . $email . " ";
- $comment = str_replace($substrToDelete, "", $comment);
- }
-
- //Length from ownCloud:
- //https://github.com/owncloud/core/blob/master/lib/private/Notification/Notification.php#L181
- $maxLen = 64;
- if (\strlen($comment) > $maxLen) {
- $ending = "...";
- $comment = substr($comment, 0, ($maxLen - \strlen($ending))) . $ending;
- }
-
- $notificationManager = \OC::$server->getNotificationManager();
- $notification = $notificationManager->createNotification();
- $notification->setApp($this->appName)
- ->setDateTime(new \DateTime())
- ->setObject("mention", $comment)
- ->setSubject("mention_info", [
- "notifierId" => $userId,
- "fileId" => $file->getId(),
- "fileName" => $file->getName(),
- "anchor" => $anchor
- ]);
-
- $shareMemberGroups = $this->shareManager->shareWithGroupMembersOnly();
- $canShare = ($file->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE;
-
- $currentUserGroups = [];
- if ($shareMemberGroups) {
- $currentUserGroups = $this->groupManager->getUserGroupIds($user);
- }
-
- $accessList = $this->getAccessList($file);
-
- foreach ($recipientIds as $recipientId) {
- $recipient = $this->userManager->get($recipientId);
- $isAvailable = \in_array($recipient, $accessList);
-
- if (!$isAvailable
- && $file->getFileInfo()->getMountPoint() instanceof \OCA\Files_External\Config\ExternalMountPoint) {
- $recipientFolder = $this->root->getUserFolder($recipientId);
- $recipientFile = $recipientFolder->getById($file->getId());
-
- $isAvailable = !empty($recipientFile);
- }
-
- if (!$isAvailable) {
- if (!$canShare) {
- continue;
- }
- if ($shareMemberGroups) {
- $recipientGroups = $this->groupManager->getUserGroupIds($recipient);
- if (empty(array_intersect($currentUserGroups, $recipientGroups))) {
- continue;
- }
- }
-
- $share = $this->shareManager->newShare();
- $share->setNode($file)
- ->setShareType(Share::SHARE_TYPE_USER)
- ->setSharedBy($userId)
- ->setSharedWith($recipientId)
- ->setShareOwner($userId)
- ->setPermissions(Constants::PERMISSION_READ);
-
- $this->shareManager->createShare($share);
-
- $this->logger->debug("mention: share $fileId to $recipientId", ["app" => $this->appName]);
- }
-
- $notification->setUser($recipientId);
-
- $notificationManager->notify($notification);
- }
-
- return ["message" => $this->trans->t("Notification sent successfully")];
- }
-
- /**
- * Reference data
- *
- * @param array $referenceData - reference data
- * @param string $path - file path
- *
- * @return array
- *
- * @NoAdminRequired
- * @PublicPage
- */
- public function reference($referenceData, $path = null) {
- $this->logger->debug("reference: " . json_encode($referenceData) . " $path", ["app" => $this->appName]);
-
- if (!$this->config->isUserAllowedToUse()) {
- return ["error" => $this->trans->t("Not permitted")];
- }
-
- $user = $this->userSession->getUser();
- if (empty($user)) {
- return ["error" => $this->trans->t("Not permitted")];
- }
-
- $userId = $user->getUID();
-
- $file = null;
- $fileId = (integer)($referenceData["fileKey"] ?? 0);
- if (!empty($fileId)
- && $referenceData["instanceId"] === $this->config->GetSystemValue("instanceid", true)) {
- list($file, $error, $share) = $this->getFile($userId, $fileId);
- }
-
- $userFolder = $this->root->getUserFolder($userId);
- if ($file === null
- && $path !== null
- && $userFolder->nodeExists($path)) {
- $node = $userFolder->get($path);
- if ($node instanceof File
- && $node->isReadable()) {
- $file = $node;
- }
- }
-
- if ($file === null) {
- $this->logger->error("Reference not found: $fileId $path", ["app" => $this->appName]);
- return ["error" => $this->trans->t("File not found")];
- }
-
- $fileName = $file->getName();
- $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
-
- $response = [
- "fileType" => $ext,
- "path" => $userFolder->getRelativePath($file->getPath()),
- "referenceData" => [
- "fileKey" => $file->getId(),
- "instanceId" => $this->config->GetSystemValue("instanceid", true),
- ],
- "url" => $this->getUrl($file, $user),
- ];
-
- if (!empty($this->config->GetDocumentServerSecret())) {
- $token = \Firebase\JWT\JWT::encode($response, $this->config->GetDocumentServerSecret(), "HS256");
- $response["token"] = $token;
- }
-
- return $response;
- }
-
- /**
- * Conversion file to Office Open XML format
- *
- * @param integer $fileId - file identifier
- * @param string $shareToken - access token
- *
- * @return array
- *
- * @NoAdminRequired
- * @PublicPage
- */
- public function convert($fileId, $shareToken = null) {
- $this->logger->debug("Convert: $fileId", ["app" => $this->appName]);
-
- if (empty($shareToken) && !$this->config->isUserAllowedToUse()) {
- return ["error" => $this->trans->t("Not permitted")];
- }
-
- $user = $this->userSession->getUser();
- $userId = null;
- if (!empty($user)) {
- $userId = $user->getUID();
- }
-
- list($file, $error, $share) = empty($shareToken) ? $this->getFile($userId, $fileId) : $this->fileUtility->getFileByToken($fileId, $shareToken);
-
- if (isset($error)) {
- $this->logger->error("Convertion: $fileId $error", ["app" => $this->appName]);
- return ["error" => $error];
- }
-
- if (!empty($shareToken) && ($share->getPermissions() & Constants::PERMISSION_CREATE) === 0) {
- $this->logger->error("Convertion in public folder without access: $fileId", ["app" => $this->appName]);
- return ["error" => $this->trans->t("You do not have enough permissions to view the file")];
- }
-
- $canDownload = $this->fileUtility->hasPermissionAttribute($file);
- if (!$canDownload) {
- return ["error" => $this->trans->t("Not permitted")];
- }
-
- $fileName = $file->getName();
- $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
- $format = $this->config->FormatsSetting()[$ext];
- if (!isset($format)) {
- $this->logger->info("Format for convertion not supported: $fileName", ["app" => $this->appName]);
- return ["error" => $this->trans->t("Format is not supported")];
- }
-
- if (!isset($format["conv"]) || $format["conv"] !== true) {
- $this->logger->info("Conversion is not required: $fileName", ["app" => $this->appName]);
- return ["error" => $this->trans->t("Conversion is not required")];
- }
-
- $internalExtension = "docx";
- switch ($format["type"]) {
- case "cell":
- $internalExtension = "xlsx";
- break;
- case "slide":
- $internalExtension = "pptx";
- break;
- }
-
- $newFileUri = null;
- $documentService = new DocumentService($this->trans, $this->config);
- $key = $this->fileUtility->getKey($file);
- $fileUrl = $this->getUrl($file, $user, $shareToken);
- try {
- $newFileUri = $documentService->GetConvertedUri($fileUrl, $ext, $internalExtension, $key);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "GetConvertedUri: " . $file->getId(), "app" => $this->appName]);
- return ["error" => $e->getMessage()];
- }
-
- $folder = $file->getParent();
- if (!($folder->isCreatable() && $folder->isUpdateable())) {
- $folder = $this->root->getUserFolder($userId);
- }
-
- try {
- $newData = $documentService->Request($newFileUri);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "Failed to download converted file", "app" => $this->appName]);
- return ["error" => $this->trans->t("Failed to download converted file")];
- }
-
- $fileNameWithoutExt = substr($fileName, 0, \strlen($fileName) - \strlen($ext) - 1);
- $newFileName = $folder->getNonExistingName($fileNameWithoutExt . "." . $internalExtension);
-
- try {
- $file = $folder->newFile($newFileName);
-
- $file->putContent($newData);
- } catch (NotPermittedException $e) {
- $this->logger->logException($e, ["message" => "Can't create file: $newFileName", "app" => $this->appName]);
- return ["error" => $this->trans->t("Can't create file")];
- } catch (ForbiddenException $e) {
- $this->logger->logException($e, ["message" => "Can't put file: $newFileName", "app" => $this->appName]);
- return ["error" => $this->trans->t("Can't create file")];
- }
-
- $fileInfo = $file->getFileInfo();
-
- $result = Helper::formatFileInfo($fileInfo);
- return $result;
- }
-
- /**
- * Save file to folder
- *
- * @param string $name - file name
- * @param string $dir - folder path
- * @param string $url - file url
- *
- * @return array
- *
- * @NoAdminRequired
- * @PublicPage
- */
- public function save($name, $dir, $url) {
- $this->logger->debug("Save: $name", ["app" => $this->appName]);
-
- if (!$this->config->isUserAllowedToUse()) {
- return ["error" => $this->trans->t("Not permitted")];
- }
-
- $userId = $this->userSession->getUser()->getUID();
- $userFolder = $this->root->getUserFolder($userId);
-
- $folder = $userFolder->get($dir);
-
- if ($folder === null) {
- $this->logger->error("Folder for saving file was not found: $dir", ["app" => $this->appName]);
- return ["error" => $this->trans->t("The required folder was not found")];
- }
- if (!($folder->isCreatable() && $folder->isUpdateable())) {
- $this->logger->error("Folder for saving file without permission: $dir", ["app" => $this->appName]);
- return ["error" => $this->trans->t("You don't have enough permission to create")];
- }
-
- $url = $this->config->ReplaceDocumentServerUrlToInternal($url);
-
- try {
- $documentService = new DocumentService($this->trans, $this->config);
- $newData = $documentService->Request($url);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "Failed to download file for saving", "app" => $this->appName]);
- return ["error" => $this->trans->t("Download failed")];
- }
-
- $name = $folder->getNonExistingName($name);
-
- try {
- $file = $folder->newFile($name);
-
- $file->putContent($newData);
- } catch (NotPermittedException $e) {
- $this->logger->logException($e, ["message" => "Can't save file: $name", "app" => $this->appName]);
- return ["error" => $this->trans->t("Can't create file")];
- } catch (ForbiddenException $e) {
- $this->logger->logException($e, ["message" => "Can't put file: $name", "app" => $this->appName]);
- return ["error" => $this->trans->t("Can't create file")];
- }
-
- $fileInfo = $file->getFileInfo();
-
- $result = Helper::formatFileInfo($fileInfo);
- return $result;
- }
-
- /**
- * Get versions history for file
- *
- * @param integer $fileId - file identifier
- *
- * @return array
- *
- * @NoAdminRequired
- */
- public function history($fileId) {
- $this->logger->debug("Request history for: $fileId", ["app" => $this->appName]);
-
- if (!$this->config->isUserAllowedToUse()) {
- return ["error" => $this->trans->t("Not permitted")];
- }
-
- $history = [];
-
- $user = $this->userSession->getUser();
- $userId = null;
- if (!empty($user)) {
- $userId = $user->getUID();
- }
-
- list($file, $error, $share) = $this->getFile($userId, $fileId);
-
- if (isset($error)) {
- $this->logger->error("History: $fileId $error", ["app" => $this->appName]);
- return ["error" => $error];
- }
-
- if ($fileId === 0) {
- $fileId = $file->getId();
- }
-
- $ownerId = null;
- $owner = $file->getFileInfo()->getOwner();
- if ($owner !== null) {
- $ownerId = $owner->getUID();
- }
-
- $versions = [];
- if ($this->versionManager->available
- && $owner !== null) {
- $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
- }
-
- $prevVersion = "";
- $versionNum = 0;
- foreach ($versions as $version) {
- $versionNum = $versionNum + 1;
-
- $key = $this->fileUtility->getVersionKey($version);
- $key = DocumentService::GenerateRevisionId($key);
-
- $historyItem = [
- "created" => $version->getTimestamp(),
- "key" => $key,
- "version" => $versionNum
- ];
-
- $versionId = $version->getRevisionId();
-
- $author = FileVersions::getAuthor($ownerId, $fileId, $versionId);
- $authorId = $author !== null ? $author["id"] : $ownerId;
- $authorName = $author !== null ? $author["name"] : $owner->getDisplayName();
-
- $historyItem["user"] = [
- "id" => $this->buildUserId($authorId),
- "name" => $authorName
- ];
-
- $historyData = FileVersions::getHistoryData($ownerId, $fileId, $versionId, $prevVersion);
- if ($historyData !== null) {
- $historyItem["changes"] = $historyData["changes"];
- $historyItem["serverVersion"] = $historyData["serverVersion"];
- }
-
- $prevVersion = $versionId;
-
- array_push($history, $historyItem);
- }
-
- $key = $this->fileUtility->getKey($file, true);
- $key = DocumentService::GenerateRevisionId($key);
-
- $historyItem = [
- "created" => $file->getMTime(),
- "key" => $key,
- "version" => $versionNum + 1
- ];
-
- $versionId = $file->getFileInfo()->getMtime();
-
- $author = FileVersions::getAuthor($ownerId, $fileId, $versionId);
- if ($author !== null) {
- $historyItem["user"] = [
- "id" => $this->buildUserId($author["id"]),
- "name" => $author["name"]
- ];
- } elseif ($owner !== null) {
- $historyItem["user"] = [
- "id" => $this->buildUserId($ownerId),
- "name" => $owner->getDisplayName()
- ];
- }
-
- $historyData = FileVersions::getHistoryData($ownerId, $fileId, $versionId, $prevVersion);
- if ($historyData !== null) {
- $historyItem["changes"] = $historyData["changes"];
- $historyItem["serverVersion"] = $historyData["serverVersion"];
- }
-
- array_push($history, $historyItem);
-
- return $history;
- }
-
- /**
- * Get file attributes of specific version
- *
- * @param integer $fileId - file identifier
- * @param integer $version - file version
- *
- * @return array
- *
- * @NoAdminRequired
- */
- public function version($fileId, $version) {
- $this->logger->debug("Request version for: $fileId ($version)", ["app" => $this->appName]);
-
- if (!$this->config->isUserAllowedToUse()) {
- return ["error" => $this->trans->t("Not permitted")];
- }
-
- $version = empty($version) ? null : $version;
-
- $user = $this->userSession->getUser();
- $userId = null;
- if (!empty($user)) {
- $userId = $user->getUID();
- }
-
- list($file, $error, $share) = $this->getFile($userId, $fileId);
-
- if (isset($error)) {
- $this->logger->error("History: $fileId $error", ["app" => $this->appName]);
- return ["error" => $error];
- }
-
- if ($fileId === 0) {
- $fileId = $file->getId();
- }
-
- $owner = null;
- $ownerId = null;
- $versions = [];
- if ($this->versionManager->available) {
- $owner = $file->getFileInfo()->getOwner();
- if ($owner !== null) {
- $ownerId = $owner->getUID();
- $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
- }
- }
-
- $key = null;
- $fileUrl = null;
- $versionId = null;
- if ($version > \count($versions)) {
- $key = $this->fileUtility->getKey($file, true);
- $versionId = $file->getFileInfo()->getMtime();
-
- $fileUrl = $this->getUrl($file, $user);
- } else {
- $fileVersion = array_values($versions)[$version - 1];
-
- $key = $this->fileUtility->getVersionKey($fileVersion);
- $versionId = $fileVersion->getRevisionId();
-
- $fileUrl = $this->getUrl($file, $user, null, $version);
- }
- $key = DocumentService::GenerateRevisionId($key);
- $fileName = $file->getName();
- $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
-
- $result = [
- "fileType" => $ext,
- "url" => $fileUrl,
- "version" => $version,
- "key" => $key
- ];
-
- if ($version > 1
- && \count($versions) >= $version - 1
- && FileVersions::hasChanges($ownerId, $fileId, $versionId)) {
- $changesUrl = $this->getUrl($file, $user, null, $version, true);
- $result["changesUrl"] = $changesUrl;
-
- $prevVersion = array_values($versions)[$version - 2];
- $prevVersionKey = $this->fileUtility->getVersionKey($prevVersion);
- $prevVersionKey = DocumentService::GenerateRevisionId($prevVersionKey);
-
- $prevVersionUrl = $this->getUrl($file, $user, null, $version - 1);
-
- $result["previous"] = [
- "fileType" => $ext,
- "key" => $prevVersionKey,
- "url" => $prevVersionUrl
- ];
- }
-
- if (!empty($this->config->GetDocumentServerSecret())) {
- $token = \Firebase\JWT\JWT::encode($result, $this->config->GetDocumentServerSecret(), "HS256");
- $result["token"] = $token;
- }
-
- return $result;
- }
-
- /**
- * Restore file version
- *
- * @param integer $fileId - file identifier
- * @param integer $version - file version
- *
- * @return array
- *
- * @NoAdminRequired
- * @PublicPage
- */
- public function restore($fileId, $version) {
- $this->logger->debug("Request restore version for: $fileId ($version)", ["app" => $this->appName]);
-
- if (!$this->config->isUserAllowedToUse()) {
- return ["error" => $this->trans->t("Not permitted")];
- }
-
- $version = empty($version) ? null : $version;
-
- $user = $this->userSession->getUser();
- $userId = null;
- if (!empty($user)) {
- $userId = $user->getUID();
- }
-
- list($file, $error, $share) = $this->getFile($userId, $fileId);
-
- if (isset($error)) {
- $this->logger->error("Restore: $fileId $error", ["app" => $this->appName]);
- return ["error" => $error];
- }
-
- if ($fileId === 0) {
- $fileId = $file->getId();
- }
-
- $owner = null;
- $versions = [];
- if ($this->versionManager->available) {
- $owner = $file->getFileInfo()->getOwner();
- if ($owner !== null) {
- $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
- }
-
- if (\count($versions) >= $version) {
- $fileVersion = array_values($versions)[$version - 1];
- $this->versionManager->rollback($fileVersion);
- }
- }
-
- return $this->history($fileId);
- }
-
- /**
- * Get presigned url to file
- *
- * @param string $filePath - file path
- *
- * @return array
- *
- * @NoAdminRequired
- */
- public function url($filePath) {
- $this->logger->debug("Request url for: $filePath", ["app" => $this->appName]);
-
- if (!$this->config->isUserAllowedToUse()) {
- return ["error" => $this->trans->t("Not permitted")];
- }
-
- $user = $this->userSession->getUser();
- $userId = $user->getUID();
- $userFolder = $this->root->getUserFolder($userId);
-
- $file = $userFolder->get($filePath);
-
- if ($file === null) {
- $this->logger->error("File for generate presigned url was not found: $dir", ["app" => $this->appName]);
- return ["error" => $this->trans->t("File not found")];
- }
- if (!$file->isReadable()) {
- $this->logger->error("File without permission: $dir", ["app" => $this->appName]);
- return ["error" => $this->trans->t("You do not have enough permissions to view the file")];
- }
-
- $fileName = $file->getName();
- $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
- $fileUrl = $this->getUrl($file, $user);
-
- $result = [
- "fileType" => $ext,
- "url" => $fileUrl
- ];
-
- if (!empty($this->config->GetDocumentServerSecret())) {
- $token = \Firebase\JWT\JWT::encode($result, $this->config->GetDocumentServerSecret(), "HS256");
- $result["token"] = $token;
- }
-
- return $result;
- }
-
- /**
- * Download method
- *
- * @param int $fileId - file identifier
- * @param string $toExtension - file extension to download
- * @param bool $template - file is template
- *
- * @return DataDownloadResponse|TemplateResponse
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- */
- public function download($fileId, $toExtension = null, $template = false) {
- $this->logger->debug("Download: $fileId $toExtension", ["app" => $this->appName]);
-
- if (!$this->config->isUserAllowedToUse()) {
- return $this->renderError($this->trans->t("Not permitted"));
- }
-
- if ($template) {
- $templateFile = TemplateManager::GetTemplate($fileId);
-
- if (empty($templateFile)) {
- $this->logger->info("Download: template not found: $fileId", ["app" => $this->appName]);
- return $this->renderError($this->trans->t("File not found"));
- }
-
- $file = $templateFile;
- } else {
- $user = $this->userSession->getUser();
- $userId = null;
- if (!empty($user)) {
- $userId = $user->getUID();
- }
-
- list($file, $error, $share) = $this->getFile($userId, $fileId);
-
- if (isset($error)) {
- $this->logger->error("Download: $fileId $error", ["app" => $this->appName]);
- return $this->renderError($error);
- }
- }
-
- $canDownload = $this->fileUtility->hasPermissionAttribute($file);
- if (!$canDownload) {
- return $this->renderError($this->trans->t("Not permitted"));
- }
-
- $fileName = $file->getName();
- $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
- $toExtension = strtolower($toExtension);
-
- if ($toExtension === null
- || $ext === $toExtension
- || $template) {
- return new DataDownloadResponse($file->getContent(), $fileName, $file->getMimeType());
- }
-
- $newFileUri = null;
- $documentService = new DocumentService($this->trans, $this->config);
- $key = $this->fileUtility->getKey($file);
- $fileUrl = $this->getUrl($file, $user);
- try {
- $newFileUri = $documentService->GetConvertedUri($fileUrl, $ext, $toExtension, $key);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "GetConvertedUri: " . $file->getId(), "app" => $this->appName]);
- return $this->renderError($e->getMessage());
- }
-
- try {
- $newData = $documentService->Request($newFileUri);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "Failed to download converted file", "app" => $this->appName]);
- return $this->renderError($this->trans->t("Failed to download converted file"));
- }
-
- $fileNameWithoutExt = substr($fileName, 0, \strlen($fileName) - \strlen($ext) - 1);
- $newFileName = $fileNameWithoutExt . "." . $toExtension;
-
- $formats = $this->config->FormatsSetting();
-
- return new DataDownloadResponse($newData, $newFileName, $formats[$toExtension]["mime"]);
- }
-
- /**
- * Print editor section
- *
- * @param integer $fileId - file identifier
- * @param string $filePath - file path
- * @param string $shareToken - access token
- * @param integer $version - file version
- * @param bool $inframe - open in frame
- * @param bool $template - file is template
- * @param string $anchor - anchor for file content
- *
- * @return TemplateResponse|RedirectResponse
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- */
- public function index($fileId, $filePath = null, $shareToken = null, $version = 0, $inframe = false, $template = false, $anchor = null) {
- $this->logger->debug("Open: $fileId ($version) $filePath", ["app" => $this->appName]);
-
- if (empty($shareToken) && !$this->userSession->isLoggedIn()) {
- $redirectUrl = $this->urlGenerator->linkToRoute("core.login.showLoginForm", [
- "redirect_url" => $this->request->getRequestUri()
- ]);
- return new RedirectResponse($redirectUrl);
- }
-
- $shareBy = null;
- if (!empty($shareToken) && !$this->userSession->isLoggedIn()) {
- list($share, $error) = $this->fileUtility->getShare($shareToken);
- if (!empty($share)) {
- $shareBy = $share->getSharedBy();
- }
- }
-
- if (!$this->config->isUserAllowedToUse($shareBy)) {
- return $this->renderError($this->trans->t("Not permitted"));
- }
-
- $documentServerUrl = $this->config->GetDocumentServerUrl();
-
- if (empty($documentServerUrl)) {
- $this->logger->error("documentServerUrl is empty", ["app" => $this->appName]);
- return $this->renderError($this->trans->t("ONLYOFFICE app is not configured. Please contact admin"));
- }
-
- $params = [
- "documentServerUrl" => $documentServerUrl,
- "fileId" => $fileId,
- "filePath" => $filePath,
- "shareToken" => $shareToken,
- "version" => $version,
- "template" => $template,
- "inframe" => false,
- "anchor" => $anchor
- ];
-
- 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);
-
- if (preg_match("/^https?:\/\//i", $documentServerUrl)) {
- $csp->addAllowedScriptDomain($documentServerUrl);
- $csp->addAllowedFrameDomain($documentServerUrl);
- } else {
- $csp->addAllowedFrameDomain("'self'");
- }
- $response->setContentSecurityPolicy($csp);
-
- return $response;
- }
-
- /**
- * Print public editor section
- *
- * @param integer $fileId - file identifier
- * @param string $shareToken - access token
- * @param integer $version - file version
- * @param bool $inframe - open in frame
- *
- * @return TemplateResponse
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- * @PublicPage
- */
- public function PublicPage($fileId, $shareToken, $version = 0, $inframe = false) {
- return $this->index($fileId, null, $shareToken, $version, $inframe);
- }
-
- /**
- * Getting file by identifier
- *
- * @param string $userId - user identifier
- * @param integer $fileId - file identifier
- * @param string $filePath - file path
- * @param bool $template - file is template
- *
- * @return array
- */
- private function getFile($userId, $fileId, $filePath = null, $template = false) {
- if (empty($fileId)) {
- return [null, $this->trans->t("FileId is empty"), null];
- }
-
- try {
- $folder = !$template ? $this->root->getUserFolder($userId) : TemplateManager::GetGlobalTemplateDir();
- $files = $folder->getById($fileId);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "getFile: $fileId", "app" => $this->appName]);
- return [null, $this->trans->t("Invalid request"), null];
- }
-
- if (empty($files)) {
- $this->logger->info("Files not found: $fileId", ["app" => $this->appName]);
- return [null, $this->trans->t("File not found"), null];
- }
-
- $file = $files[0];
-
- if (\count($files) > 1 && !empty($filePath)) {
- $filePath = "/" . $userId . "/files" . $filePath;
- foreach ($files as $curFile) {
- if ($curFile->getPath() === $filePath) {
- $file = $curFile;
- break;
- }
- }
- }
-
- if (!$file->isReadable()) {
- return [null, $this->trans->t("You do not have enough permissions to view the file"), null];
- }
-
- return [$file, null, null];
- }
-
- /**
- * Generate secure link to download document
- *
- * @param File $file - file
- * @param IUser $user - user with access
- * @param string $shareToken - access token
- * @param integer $version - file version
- * @param bool $changes - is required url to file changes
- * @param bool $template - file is template
- *
- * @return string
- */
- private function getUrl($file, $user = null, $shareToken = null, $version = 0, $changes = false, $template = false) {
- $data = [
- "action" => "download",
- "fileId" => $file->getId()
- ];
-
- $userId = null;
- if (!empty($user)) {
- $userId = $user->getUID();
- $data["userId"] = $userId;
- }
- if (!empty($shareToken)) {
- $data["shareToken"] = $shareToken;
- }
- if ($version > 0) {
- $data["version"] = $version;
- }
- if ($changes) {
- $data["changes"] = true;
- }
- if ($template) {
- $data["template"] = true;
- }
-
- $hashUrl = $this->crypt->GetHash($data);
-
- $fileUrl = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.download", ["doc" => $hashUrl]);
-
- if (!$this->config->UseDemo() && !empty($this->config->GetStorageUrl())) {
- $fileUrl = str_replace($this->urlGenerator->getAbsoluteURL("/"), $this->config->GetStorageUrl(), $fileUrl);
- }
-
- return $fileUrl;
- }
-
- /**
- * Generate unique user identifier
- *
- * @param string $userId - current user identifier
- *
- * @return string
- */
- private function buildUserId($userId) {
- $instanceId = $this->config->GetSystemValue("instanceid", true);
- $userId = $instanceId . "_" . $userId;
- return $userId;
- }
-
- /**
- * Return list users who has access to file
- *
- * @param File $file - file
- *
- * @return array
- */
- private function getAccessList($file) {
- $result = [];
-
- foreach ($this->shareManager->getSharesByPath($file) as $share) {
- $accessList = [];
- $shareWith = $share->getSharedWith();
- if ($share->getShareType() === Share::SHARE_TYPE_GROUP) {
- $group = $this->groupManager->get($shareWith);
- $accessList = $group->getUsers();
- } elseif ($share->getShareType() === Share::SHARE_TYPE_USER) {
- array_push($accessList, $this->userManager->get($shareWith));
- }
-
- foreach ($accessList as $accessUser) {
- if (!\in_array($accessUser, $result)) {
- array_push($result, $accessUser);
- }
- }
- }
-
- if (!\in_array($file->getOwner(), $result)) {
- array_push($result, $file->getOwner());
- }
-
- return $result;
- }
-
- /**
- * Return allow autocomplete usernames
- *
- * @return bool
- */
- private function allowEnumeration() {
- return \OC::$server->getConfig()->getAppValue("core", "shareapi_allow_share_dialog_user_enumeration", "yes") === "yes";
- }
-
- /**
- * Return allow autocomplete usernames group member only
- *
- * @return bool
- */
- private function limitEnumerationToGroups() {
- if ($this->allowEnumeration()) {
- return \OC::$server->getConfig()->getAppValue("core", "shareapi_share_dialog_user_enumeration_group_members", "no") === "yes";
- }
-
- return false;
- }
-
- /**
- * Print error page
- *
- * @param string $error - error message
- * @param string $hint - error hint
- *
- * @return TemplateResponse
- */
- private function renderError($error, $hint = "") {
- return new TemplateResponse("", "error", [
- "errors" => [
- [
- "error" => $error,
- "hint" => $hint
- ]
- ]
- ], "error");
- }
+ /**
+ * Current user session
+ *
+ * @var IUserSession
+ */
+ private $userSession;
+
+ /**
+ * Current user manager
+ *
+ * @var IUserManager
+ */
+ private $userManager;
+
+ /**
+ * Root folder
+ *
+ * @var IRootFolder
+ */
+ private $root;
+
+ /**
+ * Url generator service
+ *
+ * @var IURLGenerator
+ */
+ private $urlGenerator;
+
+ /**
+ * l10n service
+ *
+ * @var IL10N
+ */
+ private $trans;
+
+ /**
+ * Logger
+ *
+ * @var ILogger
+ */
+ private $logger;
+
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ private $config;
+
+ /**
+ * Hash generator
+ *
+ * @var Crypt
+ */
+ private $crypt;
+
+ /**
+ * File utility
+ *
+ * @var FileUtility
+ */
+ private $fileUtility;
+
+ /**
+ * File version manager
+ *
+ * @var VersionManager
+ */
+ private $versionManager;
+
+ /**
+ * Share manager
+ *
+ * @var IManager
+ */
+ private $shareManager;
+
+ /**
+ * Group manager
+ *
+ * @var IGroupManager
+ */
+ private $groupManager;
+
+ /**
+ * @param string $AppName - application name
+ * @param IRequest $request - request object
+ * @param IRootFolder $root - root folder
+ * @param IUserSession $userSession - current user session
+ * @param IUserManager $userManager - current user manager
+ * @param IURLGenerator $urlGenerator - url generator service
+ * @param IL10N $trans - l10n service
+ * @param ILogger $logger - logger
+ * @param AppConfig $config - application configuration
+ * @param Crypt $crypt - hash generator
+ * @param IManager $shareManager - Share manager
+ * @param ISession $session - Session
+ * @param IGroupManager $groupManager - Group manager
+ */
+ public function __construct(
+ $AppName,
+ IRequest $request,
+ IRootFolder $root,
+ IUserSession $userSession,
+ IUserManager $userManager,
+ IURLGenerator $urlGenerator,
+ IL10N $trans,
+ ILogger $logger,
+ AppConfig $config,
+ Crypt $crypt,
+ IManager $shareManager,
+ ISession $session,
+ IGroupManager $groupManager
+ ) {
+ parent::__construct($AppName, $request);
+
+ $this->userSession = $userSession;
+ $this->userManager = $userManager;
+ $this->root = $root;
+ $this->urlGenerator = $urlGenerator;
+ $this->trans = $trans;
+ $this->logger = $logger;
+ $this->config = $config;
+ $this->crypt = $crypt;
+ $this->shareManager = $shareManager;
+ $this->groupManager = $groupManager;
+
+ $this->versionManager = new VersionManager($AppName, $root);
+
+ $this->fileUtility = new FileUtility($AppName, $trans, $logger, $config, $shareManager, $session);
+ }
+
+ /**
+ * Create new file in folder
+ *
+ * @param string $name - file name
+ * @param string $dir - folder path
+ * @param string $templateId - file identifier
+ * @param string $targetPath - file path for using as template for create
+ * @param string $shareToken - access token
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ * @PublicPage
+ */
+ public function create($name, $dir, $templateId = null, $targetPath = null, $shareToken = null) {
+ $this->logger->debug("Create: $name", ["app" => $this->appName]);
+
+ if (empty($shareToken) && !$this->config->isUserAllowedToUse()) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
+ if (empty($name)) {
+ $this->logger->error("File name for creation was not found: $name", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("Template not found")];
+ }
+
+ $user = null;
+ if (empty($shareToken)) {
+ $user = $this->userSession->getUser();
+ $userId = $user->getUID();
+ $userFolder = $this->root->getUserFolder($userId);
+ } else {
+ list($userFolder, $error, $share) = $this->fileUtility->getNodeByToken($shareToken);
+
+ if (isset($error)) {
+ $this->logger->error("Create: $error", ["app" => $this->appName]);
+ return ["error" => $error];
+ }
+
+ if ($userFolder instanceof File) {
+ return ["error" => $this->trans->t("You don't have enough permission to create")];
+ }
+
+ if (!empty($shareToken) && ($share->getPermissions() & Constants::PERMISSION_CREATE) === 0) {
+ $this->logger->error("Create in public folder without access", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("You do not have enough permissions to view the file")];
+ }
+ }
+
+ $folder = $userFolder->get($dir);
+
+ if ($folder === null) {
+ $this->logger->error("Folder for file creation was not found: $dir", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("The required folder was not found")];
+ }
+ if (!($folder->isCreatable() && $folder->isUpdateable())) {
+ $this->logger->error("Folder for file creation without permission: $dir", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("You don't have enough permission to create")];
+ }
+
+ if (!empty($templateId)) {
+ $templateFile = TemplateManager::GetTemplate($templateId);
+ if ($templateFile) {
+ $template = $templateFile->getContent();
+ }
+ } elseif (!empty($targetPath)) {
+ $targetFile = $userFolder->get($targetPath);
+
+ $canDownload = $this->fileUtility->hasPermissionAttribute($targetFile);
+ if (!$canDownload) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
+ $targetId = $targetFile->getId();
+ $targetName = $targetFile->getName();
+ $targetExt = strtolower(pathinfo($targetName, PATHINFO_EXTENSION));
+ $targetKey = $this->fileUtility->getKey($targetFile);
+
+ $fileUrl = $this->getUrl($targetFile, $user, $shareToken);
+
+ $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
+ $documentService = new DocumentService($this->trans, $this->config);
+ try {
+ $newFileUri = $documentService->GetConvertedUri($fileUrl, $targetExt, $ext, $targetKey);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "GetConvertedUri: " . $targetFile->getId(), "app" => $this->appName]);
+ return ["error" => $e->getMessage()];
+ }
+ $template = $documentService->Request($newFileUri);
+ } else {
+ $template = TemplateManager::GetEmptyTemplate($name);
+ }
+
+ if (!$template) {
+ $this->logger->error("Template for file creation not found: $name ($templateId)", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("Template not found")];
+ }
+
+ $name = $folder->getNonExistingName($name);
+
+ try {
+ $file = $folder->newFile($name);
+
+ $file->putContent($template);
+ } catch (NotPermittedException $e) {
+ $this->logger->logException($e, ["message" => "Can't create file: $name", "app" => $this->appName]);
+ return ["error" => $this->trans->t("Can't create file")];
+ } catch (ForbiddenException $e) {
+ $this->logger->logException($e, ["message" => "Can't put file: $name", "app" => $this->appName]);
+ return ["error" => $this->trans->t("Can't create file")];
+ }
+
+ $fileInfo = $file->getFileInfo();
+
+ $result = Helper::formatFileInfo($fileInfo);
+ return $result;
+ }
+
+ /**
+ * Create new file in folder from editor
+ *
+ * @param string $name - file name
+ * @param string $dir - folder path
+ * @param string $templateId - file identifier
+ *
+ * @return TemplateResponse|RedirectResponse
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ */
+ public function createNew($name, $dir, $templateId = null) {
+ $this->logger->debug("Create from editor: $name in $dir", ["app" => $this->appName]);
+
+ $result = $this->create($name, $dir, $templateId);
+ if (isset($result["error"])) {
+ return $this->renderError($result["error"]);
+ }
+
+ $openEditor = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".editor.index", ["fileId" => $result["id"]]);
+ return new RedirectResponse($openEditor);
+ }
+
+ /**
+ * Get users
+ *
+ * @param $fileId - file identifier
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ */
+ public function users($fileId) {
+ $this->logger->debug("Search users", ["app" => $this->appName]);
+ $result = [];
+
+ if (!$this->config->isUserAllowedToUse()) {
+ return $result;
+ }
+
+ if (!$this->allowEnumeration()) {
+ return $result;
+ }
+
+ $autocompleteMemberGroup = false;
+ if ($this->limitEnumerationToGroups()) {
+ $autocompleteMemberGroup = true;
+ }
+
+ $currentUser = $this->userSession->getUser();
+ $currentUserId = $currentUser->getUID();
+
+ list($file, $error, $share) = $this->getFile($currentUserId, $fileId);
+ if (isset($error)) {
+ $this->logger->error("Users: $fileId $error", ["app" => $this->appName]);
+ return $result;
+ }
+
+ $canShare = (($file->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE);
+
+ $shareMemberGroups = $this->shareManager->shareWithGroupMembersOnly();
+
+ $all = false;
+ $users = [];
+ if ($canShare) {
+ if ($shareMemberGroups || $autocompleteMemberGroup) {
+ $currentUserGroups = $this->groupManager->getUserGroupIds($currentUser);
+ foreach ($currentUserGroups as $currentUserGroup) {
+ $group = $this->groupManager->get($currentUserGroup);
+ foreach ($group->getUsers() as $user) {
+ if (!\in_array($user, $users)) {
+ array_push($users, $user);
+ }
+ }
+ }
+ } else {
+ $users = $this->userManager->search("");
+ $all = true;
+ }
+ }
+
+ if (!$all) {
+ $accessList = $this->getAccessList($file);
+ foreach ($accessList as $accessUser) {
+ if (!\in_array($accessUser, $users)) {
+ array_push($users, $accessUser);
+ }
+ }
+ }
+
+ foreach ($users as $user) {
+ $email = $user->getEMailAddress();
+ if ($user->getUID() != $currentUserId && !empty($email)) {
+ array_push($result, [
+ "email" => $email,
+ "name" => $user->getDisplayName()
+ ]);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Send notify about mention
+ *
+ * @param int $fileId - file identifier
+ * @param string $anchor - the anchor on target content
+ * @param string $comment - comment
+ * @param array $emails - emails array to whom to send notify
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ */
+ public function mention($fileId, $anchor, $comment, $emails) {
+ $this->logger->debug("mention: from $fileId to " . json_encode($emails), ["app" => $this->appName]);
+
+ if (!$this->config->isUserAllowedToUse()) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
+ if (empty($emails)) {
+ return ["error" => $this->trans->t("Failed to send notification")];
+ }
+
+ $recipientIds = [];
+ foreach ($emails as $email) {
+ $recipients = $this->userManager->getByEmail($email);
+ foreach ($recipients as $recipient) {
+ $recipientId = $recipient->getUID();
+ if (!\in_array($recipientId, $recipientIds)) {
+ array_push($recipientIds, $recipientId);
+ }
+ }
+ }
+
+ $user = $this->userSession->getUser();
+ $userId = null;
+ if (!empty($user)) {
+ $userId = $user->getUID();
+ }
+
+ list($file, $error, $share) = $this->getFile($userId, $fileId);
+ if (isset($error)) {
+ $this->logger->error("Mention: $fileId $error", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("Failed to send notification")];
+ }
+
+ foreach ($emails as $email) {
+ $substrToDelete = "+" . $email . " ";
+ $comment = str_replace($substrToDelete, "", $comment);
+ }
+
+ //Length from ownCloud:
+ //https://github.com/owncloud/core/blob/master/lib/private/Notification/Notification.php#L181
+ $maxLen = 64;
+ if (\strlen($comment) > $maxLen) {
+ $ending = "...";
+ $comment = substr($comment, 0, ($maxLen - \strlen($ending))) . $ending;
+ }
+
+ $notificationManager = \OC::$server->getNotificationManager();
+ $notification = $notificationManager->createNotification();
+ $notification->setApp($this->appName)
+ ->setDateTime(new \DateTime())
+ ->setObject("mention", $comment)
+ ->setSubject("mention_info", [
+ "notifierId" => $userId,
+ "fileId" => $file->getId(),
+ "fileName" => $file->getName(),
+ "anchor" => $anchor
+ ]);
+
+ $shareMemberGroups = $this->shareManager->shareWithGroupMembersOnly();
+ $canShare = ($file->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE;
+
+ $currentUserGroups = [];
+ if ($shareMemberGroups) {
+ $currentUserGroups = $this->groupManager->getUserGroupIds($user);
+ }
+
+ $accessList = $this->getAccessList($file);
+
+ foreach ($recipientIds as $recipientId) {
+ $recipient = $this->userManager->get($recipientId);
+ $isAvailable = \in_array($recipient, $accessList);
+
+ if (!$isAvailable
+ && $file->getFileInfo()->getMountPoint() instanceof \OCA\Files_External\Config\ExternalMountPoint) {
+ $recipientFolder = $this->root->getUserFolder($recipientId);
+ $recipientFile = $recipientFolder->getById($file->getId());
+
+ $isAvailable = !empty($recipientFile);
+ }
+
+ if (!$isAvailable) {
+ if (!$canShare) {
+ continue;
+ }
+ if ($shareMemberGroups) {
+ $recipientGroups = $this->groupManager->getUserGroupIds($recipient);
+ if (empty(array_intersect($currentUserGroups, $recipientGroups))) {
+ continue;
+ }
+ }
+
+ $share = $this->shareManager->newShare();
+ $share->setNode($file)
+ ->setShareType(Share::SHARE_TYPE_USER)
+ ->setSharedBy($userId)
+ ->setSharedWith($recipientId)
+ ->setShareOwner($userId)
+ ->setPermissions(Constants::PERMISSION_READ);
+
+ $this->shareManager->createShare($share);
+
+ $this->logger->debug("mention: share $fileId to $recipientId", ["app" => $this->appName]);
+ }
+
+ $notification->setUser($recipientId);
+
+ $notificationManager->notify($notification);
+ }
+
+ return ["message" => $this->trans->t("Notification sent successfully")];
+ }
+
+ /**
+ * Reference data
+ *
+ * @param array $referenceData - reference data
+ * @param string $path - file path
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ * @PublicPage
+ */
+ public function reference($referenceData, $path = null) {
+ $this->logger->debug("reference: " . json_encode($referenceData) . " $path", ["app" => $this->appName]);
+
+ if (!$this->config->isUserAllowedToUse()) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
+ $user = $this->userSession->getUser();
+ if (empty($user)) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
+ $userId = $user->getUID();
+
+ $file = null;
+ $fileId = (integer)($referenceData["fileKey"] ?? 0);
+ if (!empty($fileId)
+ && $referenceData["instanceId"] === $this->config->GetSystemValue("instanceid", true)) {
+ list($file, $error, $share) = $this->getFile($userId, $fileId);
+ }
+
+ $userFolder = $this->root->getUserFolder($userId);
+ if ($file === null
+ && $path !== null
+ && $userFolder->nodeExists($path)) {
+ $node = $userFolder->get($path);
+ if ($node instanceof File
+ && $node->isReadable()) {
+ $file = $node;
+ }
+ }
+
+ if ($file === null) {
+ $this->logger->error("Reference not found: $fileId $path", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("File not found")];
+ }
+
+ $fileName = $file->getName();
+ $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
+
+ $response = [
+ "fileType" => $ext,
+ "path" => $userFolder->getRelativePath($file->getPath()),
+ "referenceData" => [
+ "fileKey" => $file->getId(),
+ "instanceId" => $this->config->GetSystemValue("instanceid", true),
+ ],
+ "url" => $this->getUrl($file, $user),
+ ];
+
+ if (!empty($this->config->GetDocumentServerSecret())) {
+ $token = \Firebase\JWT\JWT::encode($response, $this->config->GetDocumentServerSecret(), "HS256");
+ $response["token"] = $token;
+ }
+
+ return $response;
+ }
+
+ /**
+ * Conversion file to Office Open XML format
+ *
+ * @param integer $fileId - file identifier
+ * @param string $shareToken - access token
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ * @PublicPage
+ */
+ public function convert($fileId, $shareToken = null) {
+ $this->logger->debug("Convert: $fileId", ["app" => $this->appName]);
+
+ if (empty($shareToken) && !$this->config->isUserAllowedToUse()) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
+ $user = $this->userSession->getUser();
+ $userId = null;
+ if (!empty($user)) {
+ $userId = $user->getUID();
+ }
+
+ list($file, $error, $share) = empty($shareToken) ? $this->getFile($userId, $fileId) : $this->fileUtility->getFileByToken($fileId, $shareToken);
+
+ if (isset($error)) {
+ $this->logger->error("Convertion: $fileId $error", ["app" => $this->appName]);
+ return ["error" => $error];
+ }
+
+ if (!empty($shareToken) && ($share->getPermissions() & Constants::PERMISSION_CREATE) === 0) {
+ $this->logger->error("Convertion in public folder without access: $fileId", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("You do not have enough permissions to view the file")];
+ }
+
+ $canDownload = $this->fileUtility->hasPermissionAttribute($file);
+ if (!$canDownload) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
+ $fileName = $file->getName();
+ $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
+ $format = $this->config->FormatsSetting()[$ext];
+ if (!isset($format)) {
+ $this->logger->info("Format for convertion not supported: $fileName", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("Format is not supported")];
+ }
+
+ if (!isset($format["conv"]) || $format["conv"] !== true) {
+ $this->logger->info("Conversion is not required: $fileName", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("Conversion is not required")];
+ }
+
+ $internalExtension = "docx";
+ switch ($format["type"]) {
+ case "cell":
+ $internalExtension = "xlsx";
+ break;
+ case "slide":
+ $internalExtension = "pptx";
+ break;
+ }
+
+ $newFileUri = null;
+ $documentService = new DocumentService($this->trans, $this->config);
+ $key = $this->fileUtility->getKey($file);
+ $fileUrl = $this->getUrl($file, $user, $shareToken);
+ try {
+ $newFileUri = $documentService->GetConvertedUri($fileUrl, $ext, $internalExtension, $key);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "GetConvertedUri: " . $file->getId(), "app" => $this->appName]);
+ return ["error" => $e->getMessage()];
+ }
+
+ $folder = $file->getParent();
+ if (!($folder->isCreatable() && $folder->isUpdateable())) {
+ $folder = $this->root->getUserFolder($userId);
+ }
+
+ try {
+ $newData = $documentService->Request($newFileUri);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "Failed to download converted file", "app" => $this->appName]);
+ return ["error" => $this->trans->t("Failed to download converted file")];
+ }
+
+ $fileNameWithoutExt = substr($fileName, 0, \strlen($fileName) - \strlen($ext) - 1);
+ $newFileName = $folder->getNonExistingName($fileNameWithoutExt . "." . $internalExtension);
+
+ try {
+ $file = $folder->newFile($newFileName);
+
+ $file->putContent($newData);
+ } catch (NotPermittedException $e) {
+ $this->logger->logException($e, ["message" => "Can't create file: $newFileName", "app" => $this->appName]);
+ return ["error" => $this->trans->t("Can't create file")];
+ } catch (ForbiddenException $e) {
+ $this->logger->logException($e, ["message" => "Can't put file: $newFileName", "app" => $this->appName]);
+ return ["error" => $this->trans->t("Can't create file")];
+ }
+
+ $fileInfo = $file->getFileInfo();
+
+ $result = Helper::formatFileInfo($fileInfo);
+ return $result;
+ }
+
+ /**
+ * Save file to folder
+ *
+ * @param string $name - file name
+ * @param string $dir - folder path
+ * @param string $url - file url
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ * @PublicPage
+ */
+ public function save($name, $dir, $url) {
+ $this->logger->debug("Save: $name", ["app" => $this->appName]);
+
+ if (!$this->config->isUserAllowedToUse()) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
+ $userId = $this->userSession->getUser()->getUID();
+ $userFolder = $this->root->getUserFolder($userId);
+
+ $folder = $userFolder->get($dir);
+
+ if ($folder === null) {
+ $this->logger->error("Folder for saving file was not found: $dir", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("The required folder was not found")];
+ }
+ if (!($folder->isCreatable() && $folder->isUpdateable())) {
+ $this->logger->error("Folder for saving file without permission: $dir", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("You don't have enough permission to create")];
+ }
+
+ $url = $this->config->ReplaceDocumentServerUrlToInternal($url);
+
+ try {
+ $documentService = new DocumentService($this->trans, $this->config);
+ $newData = $documentService->Request($url);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "Failed to download file for saving", "app" => $this->appName]);
+ return ["error" => $this->trans->t("Download failed")];
+ }
+
+ $name = $folder->getNonExistingName($name);
+
+ try {
+ $file = $folder->newFile($name);
+
+ $file->putContent($newData);
+ } catch (NotPermittedException $e) {
+ $this->logger->logException($e, ["message" => "Can't save file: $name", "app" => $this->appName]);
+ return ["error" => $this->trans->t("Can't create file")];
+ } catch (ForbiddenException $e) {
+ $this->logger->logException($e, ["message" => "Can't put file: $name", "app" => $this->appName]);
+ return ["error" => $this->trans->t("Can't create file")];
+ }
+
+ $fileInfo = $file->getFileInfo();
+
+ $result = Helper::formatFileInfo($fileInfo);
+ return $result;
+ }
+
+ /**
+ * Get versions history for file
+ *
+ * @param integer $fileId - file identifier
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ */
+ public function history($fileId) {
+ $this->logger->debug("Request history for: $fileId", ["app" => $this->appName]);
+
+ if (!$this->config->isUserAllowedToUse()) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
+ $history = [];
+
+ $user = $this->userSession->getUser();
+ $userId = null;
+ if (!empty($user)) {
+ $userId = $user->getUID();
+ }
+
+ list($file, $error, $share) = $this->getFile($userId, $fileId);
+
+ if (isset($error)) {
+ $this->logger->error("History: $fileId $error", ["app" => $this->appName]);
+ return ["error" => $error];
+ }
+
+ if ($fileId === 0) {
+ $fileId = $file->getId();
+ }
+
+ $ownerId = null;
+ $owner = $file->getFileInfo()->getOwner();
+ if ($owner !== null) {
+ $ownerId = $owner->getUID();
+ }
+
+ $versions = [];
+ if ($this->versionManager->available
+ && $owner !== null) {
+ $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
+ }
+
+ $prevVersion = "";
+ $versionNum = 0;
+ foreach ($versions as $version) {
+ $versionNum = $versionNum + 1;
+
+ $key = $this->fileUtility->getVersionKey($version);
+ $key = DocumentService::GenerateRevisionId($key);
+
+ $historyItem = [
+ "created" => $version->getTimestamp(),
+ "key" => $key,
+ "version" => $versionNum
+ ];
+
+ $versionId = $version->getRevisionId();
+
+ $author = FileVersions::getAuthor($ownerId, $fileId, $versionId);
+ $authorId = $author !== null ? $author["id"] : $ownerId;
+ $authorName = $author !== null ? $author["name"] : $owner->getDisplayName();
+
+ $historyItem["user"] = [
+ "id" => $this->buildUserId($authorId),
+ "name" => $authorName
+ ];
+
+ $historyData = FileVersions::getHistoryData($ownerId, $fileId, $versionId, $prevVersion);
+ if ($historyData !== null) {
+ $historyItem["changes"] = $historyData["changes"];
+ $historyItem["serverVersion"] = $historyData["serverVersion"];
+ }
+
+ $prevVersion = $versionId;
+
+ array_push($history, $historyItem);
+ }
+
+ $key = $this->fileUtility->getKey($file, true);
+ $key = DocumentService::GenerateRevisionId($key);
+
+ $historyItem = [
+ "created" => $file->getMTime(),
+ "key" => $key,
+ "version" => $versionNum + 1
+ ];
+
+ $versionId = $file->getFileInfo()->getMtime();
+
+ $author = FileVersions::getAuthor($ownerId, $fileId, $versionId);
+ if ($author !== null) {
+ $historyItem["user"] = [
+ "id" => $this->buildUserId($author["id"]),
+ "name" => $author["name"]
+ ];
+ } elseif ($owner !== null) {
+ $historyItem["user"] = [
+ "id" => $this->buildUserId($ownerId),
+ "name" => $owner->getDisplayName()
+ ];
+ }
+
+ $historyData = FileVersions::getHistoryData($ownerId, $fileId, $versionId, $prevVersion);
+ if ($historyData !== null) {
+ $historyItem["changes"] = $historyData["changes"];
+ $historyItem["serverVersion"] = $historyData["serverVersion"];
+ }
+
+ array_push($history, $historyItem);
+
+ return $history;
+ }
+
+ /**
+ * Get file attributes of specific version
+ *
+ * @param integer $fileId - file identifier
+ * @param integer $version - file version
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ */
+ public function version($fileId, $version) {
+ $this->logger->debug("Request version for: $fileId ($version)", ["app" => $this->appName]);
+
+ if (!$this->config->isUserAllowedToUse()) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
+ $version = empty($version) ? null : $version;
+
+ $user = $this->userSession->getUser();
+ $userId = null;
+ if (!empty($user)) {
+ $userId = $user->getUID();
+ }
+
+ list($file, $error, $share) = $this->getFile($userId, $fileId);
+
+ if (isset($error)) {
+ $this->logger->error("History: $fileId $error", ["app" => $this->appName]);
+ return ["error" => $error];
+ }
+
+ if ($fileId === 0) {
+ $fileId = $file->getId();
+ }
+
+ $owner = null;
+ $ownerId = null;
+ $versions = [];
+ if ($this->versionManager->available) {
+ $owner = $file->getFileInfo()->getOwner();
+ if ($owner !== null) {
+ $ownerId = $owner->getUID();
+ $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
+ }
+ }
+
+ $key = null;
+ $fileUrl = null;
+ $versionId = null;
+ if ($version > \count($versions)) {
+ $key = $this->fileUtility->getKey($file, true);
+ $versionId = $file->getFileInfo()->getMtime();
+
+ $fileUrl = $this->getUrl($file, $user);
+ } else {
+ $fileVersion = array_values($versions)[$version - 1];
+
+ $key = $this->fileUtility->getVersionKey($fileVersion);
+ $versionId = $fileVersion->getRevisionId();
+
+ $fileUrl = $this->getUrl($file, $user, null, $version);
+ }
+ $key = DocumentService::GenerateRevisionId($key);
+ $fileName = $file->getName();
+ $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
+
+ $result = [
+ "fileType" => $ext,
+ "url" => $fileUrl,
+ "version" => $version,
+ "key" => $key
+ ];
+
+ if ($version > 1
+ && \count($versions) >= $version - 1
+ && FileVersions::hasChanges($ownerId, $fileId, $versionId)) {
+ $changesUrl = $this->getUrl($file, $user, null, $version, true);
+ $result["changesUrl"] = $changesUrl;
+
+ $prevVersion = array_values($versions)[$version - 2];
+ $prevVersionKey = $this->fileUtility->getVersionKey($prevVersion);
+ $prevVersionKey = DocumentService::GenerateRevisionId($prevVersionKey);
+
+ $prevVersionUrl = $this->getUrl($file, $user, null, $version - 1);
+
+ $result["previous"] = [
+ "fileType" => $ext,
+ "key" => $prevVersionKey,
+ "url" => $prevVersionUrl
+ ];
+ }
+
+ if (!empty($this->config->GetDocumentServerSecret())) {
+ $token = \Firebase\JWT\JWT::encode($result, $this->config->GetDocumentServerSecret(), "HS256");
+ $result["token"] = $token;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Restore file version
+ *
+ * @param integer $fileId - file identifier
+ * @param integer $version - file version
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ * @PublicPage
+ */
+ public function restore($fileId, $version) {
+ $this->logger->debug("Request restore version for: $fileId ($version)", ["app" => $this->appName]);
+
+ if (!$this->config->isUserAllowedToUse()) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
+ $version = empty($version) ? null : $version;
+
+ $user = $this->userSession->getUser();
+ $userId = null;
+ if (!empty($user)) {
+ $userId = $user->getUID();
+ }
+
+ list($file, $error, $share) = $this->getFile($userId, $fileId);
+
+ if (isset($error)) {
+ $this->logger->error("Restore: $fileId $error", ["app" => $this->appName]);
+ return ["error" => $error];
+ }
+
+ if ($fileId === 0) {
+ $fileId = $file->getId();
+ }
+
+ $owner = null;
+ $versions = [];
+ if ($this->versionManager->available) {
+ $owner = $file->getFileInfo()->getOwner();
+ if ($owner !== null) {
+ $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
+ }
+
+ if (\count($versions) >= $version) {
+ $fileVersion = array_values($versions)[$version - 1];
+ $this->versionManager->rollback($fileVersion);
+ }
+ }
+
+ return $this->history($fileId);
+ }
+
+ /**
+ * Get presigned url to file
+ *
+ * @param string $filePath - file path
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ */
+ public function url($filePath) {
+ $this->logger->debug("Request url for: $filePath", ["app" => $this->appName]);
+
+ if (!$this->config->isUserAllowedToUse()) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
+ $user = $this->userSession->getUser();
+ $userId = $user->getUID();
+ $userFolder = $this->root->getUserFolder($userId);
+
+ $file = $userFolder->get($filePath);
+
+ if ($file === null) {
+ $this->logger->error("File for generate presigned url was not found: $dir", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("File not found")];
+ }
+ if (!$file->isReadable()) {
+ $this->logger->error("File without permission: $dir", ["app" => $this->appName]);
+ return ["error" => $this->trans->t("You do not have enough permissions to view the file")];
+ }
+
+ $fileName = $file->getName();
+ $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
+ $fileUrl = $this->getUrl($file, $user);
+
+ $result = [
+ "fileType" => $ext,
+ "url" => $fileUrl
+ ];
+
+ if (!empty($this->config->GetDocumentServerSecret())) {
+ $token = \Firebase\JWT\JWT::encode($result, $this->config->GetDocumentServerSecret(), "HS256");
+ $result["token"] = $token;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Download method
+ *
+ * @param int $fileId - file identifier
+ * @param string $toExtension - file extension to download
+ * @param bool $template - file is template
+ *
+ * @return DataDownloadResponse|TemplateResponse
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ */
+ public function download($fileId, $toExtension = null, $template = false) {
+ $this->logger->debug("Download: $fileId $toExtension", ["app" => $this->appName]);
+
+ if (!$this->config->isUserAllowedToUse()) {
+ return $this->renderError($this->trans->t("Not permitted"));
+ }
+
+ if ($template) {
+ $templateFile = TemplateManager::GetTemplate($fileId);
+
+ if (empty($templateFile)) {
+ $this->logger->info("Download: template not found: $fileId", ["app" => $this->appName]);
+ return $this->renderError($this->trans->t("File not found"));
+ }
+
+ $file = $templateFile;
+ } else {
+ $user = $this->userSession->getUser();
+ $userId = null;
+ if (!empty($user)) {
+ $userId = $user->getUID();
+ }
+
+ list($file, $error, $share) = $this->getFile($userId, $fileId);
+
+ if (isset($error)) {
+ $this->logger->error("Download: $fileId $error", ["app" => $this->appName]);
+ return $this->renderError($error);
+ }
+ }
+
+ $canDownload = $this->fileUtility->hasPermissionAttribute($file);
+ if (!$canDownload) {
+ return $this->renderError($this->trans->t("Not permitted"));
+ }
+
+ $fileName = $file->getName();
+ $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
+ $toExtension = strtolower($toExtension);
+
+ if ($toExtension === null
+ || $ext === $toExtension
+ || $template) {
+ return new DataDownloadResponse($file->getContent(), $fileName, $file->getMimeType());
+ }
+
+ $newFileUri = null;
+ $documentService = new DocumentService($this->trans, $this->config);
+ $key = $this->fileUtility->getKey($file);
+ $fileUrl = $this->getUrl($file, $user);
+ try {
+ $newFileUri = $documentService->GetConvertedUri($fileUrl, $ext, $toExtension, $key);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "GetConvertedUri: " . $file->getId(), "app" => $this->appName]);
+ return $this->renderError($e->getMessage());
+ }
+
+ try {
+ $newData = $documentService->Request($newFileUri);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "Failed to download converted file", "app" => $this->appName]);
+ return $this->renderError($this->trans->t("Failed to download converted file"));
+ }
+
+ $fileNameWithoutExt = substr($fileName, 0, \strlen($fileName) - \strlen($ext) - 1);
+ $newFileName = $fileNameWithoutExt . "." . $toExtension;
+
+ $formats = $this->config->FormatsSetting();
+
+ return new DataDownloadResponse($newData, $newFileName, $formats[$toExtension]["mime"]);
+ }
+
+ /**
+ * Print editor section
+ *
+ * @param integer $fileId - file identifier
+ * @param string $filePath - file path
+ * @param string $shareToken - access token
+ * @param integer $version - file version
+ * @param bool $inframe - open in frame
+ * @param bool $template - file is template
+ * @param string $anchor - anchor for file content
+ *
+ * @return TemplateResponse|RedirectResponse
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ */
+ public function index($fileId, $filePath = null, $shareToken = null, $version = 0, $inframe = false, $template = false, $anchor = null) {
+ $this->logger->debug("Open: $fileId ($version) $filePath", ["app" => $this->appName]);
+
+ if (empty($shareToken) && !$this->userSession->isLoggedIn()) {
+ $redirectUrl = $this->urlGenerator->linkToRoute("core.login.showLoginForm", [
+ "redirect_url" => $this->request->getRequestUri()
+ ]);
+ return new RedirectResponse($redirectUrl);
+ }
+
+ $shareBy = null;
+ if (!empty($shareToken) && !$this->userSession->isLoggedIn()) {
+ list($share, $error) = $this->fileUtility->getShare($shareToken);
+ if (!empty($share)) {
+ $shareBy = $share->getSharedBy();
+ }
+ }
+
+ if (!$this->config->isUserAllowedToUse($shareBy)) {
+ return $this->renderError($this->trans->t("Not permitted"));
+ }
+
+ $documentServerUrl = $this->config->GetDocumentServerUrl();
+
+ if (empty($documentServerUrl)) {
+ $this->logger->error("documentServerUrl is empty", ["app" => $this->appName]);
+ return $this->renderError($this->trans->t("ONLYOFFICE app is not configured. Please contact admin"));
+ }
+
+ $params = [
+ "documentServerUrl" => $documentServerUrl,
+ "fileId" => $fileId,
+ "filePath" => $filePath,
+ "shareToken" => $shareToken,
+ "version" => $version,
+ "template" => $template,
+ "inframe" => false,
+ "anchor" => $anchor
+ ];
+
+ 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);
+
+ if (preg_match("/^https?:\/\//i", $documentServerUrl)) {
+ $csp->addAllowedScriptDomain($documentServerUrl);
+ $csp->addAllowedFrameDomain($documentServerUrl);
+ } else {
+ $csp->addAllowedFrameDomain("'self'");
+ }
+ $response->setContentSecurityPolicy($csp);
+
+ return $response;
+ }
+
+ /**
+ * Print public editor section
+ *
+ * @param integer $fileId - file identifier
+ * @param string $shareToken - access token
+ * @param integer $version - file version
+ * @param bool $inframe - open in frame
+ *
+ * @return TemplateResponse
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
+ */
+ public function PublicPage($fileId, $shareToken, $version = 0, $inframe = false) {
+ return $this->index($fileId, null, $shareToken, $version, $inframe);
+ }
+
+ /**
+ * Getting file by identifier
+ *
+ * @param string $userId - user identifier
+ * @param integer $fileId - file identifier
+ * @param string $filePath - file path
+ * @param bool $template - file is template
+ *
+ * @return array
+ */
+ private function getFile($userId, $fileId, $filePath = null, $template = false) {
+ if (empty($fileId)) {
+ return [null, $this->trans->t("FileId is empty"), null];
+ }
+
+ try {
+ $folder = !$template ? $this->root->getUserFolder($userId) : TemplateManager::GetGlobalTemplateDir();
+ $files = $folder->getById($fileId);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "getFile: $fileId", "app" => $this->appName]);
+ return [null, $this->trans->t("Invalid request"), null];
+ }
+
+ if (empty($files)) {
+ $this->logger->info("Files not found: $fileId", ["app" => $this->appName]);
+ return [null, $this->trans->t("File not found"), null];
+ }
+
+ $file = $files[0];
+
+ if (\count($files) > 1 && !empty($filePath)) {
+ $filePath = "/" . $userId . "/files" . $filePath;
+ foreach ($files as $curFile) {
+ if ($curFile->getPath() === $filePath) {
+ $file = $curFile;
+ break;
+ }
+ }
+ }
+
+ if (!$file->isReadable()) {
+ return [null, $this->trans->t("You do not have enough permissions to view the file"), null];
+ }
+
+ return [$file, null, null];
+ }
+
+ /**
+ * Generate secure link to download document
+ *
+ * @param File $file - file
+ * @param IUser $user - user with access
+ * @param string $shareToken - access token
+ * @param integer $version - file version
+ * @param bool $changes - is required url to file changes
+ * @param bool $template - file is template
+ *
+ * @return string
+ */
+ private function getUrl($file, $user = null, $shareToken = null, $version = 0, $changes = false, $template = false) {
+ $data = [
+ "action" => "download",
+ "fileId" => $file->getId()
+ ];
+
+ $userId = null;
+ if (!empty($user)) {
+ $userId = $user->getUID();
+ $data["userId"] = $userId;
+ }
+ if (!empty($shareToken)) {
+ $data["shareToken"] = $shareToken;
+ }
+ if ($version > 0) {
+ $data["version"] = $version;
+ }
+ if ($changes) {
+ $data["changes"] = true;
+ }
+ if ($template) {
+ $data["template"] = true;
+ }
+
+ $hashUrl = $this->crypt->GetHash($data);
+
+ $fileUrl = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.download", ["doc" => $hashUrl]);
+
+ if (!$this->config->UseDemo() && !empty($this->config->GetStorageUrl())) {
+ $fileUrl = str_replace($this->urlGenerator->getAbsoluteURL("/"), $this->config->GetStorageUrl(), $fileUrl);
+ }
+
+ return $fileUrl;
+ }
+
+ /**
+ * Generate unique user identifier
+ *
+ * @param string $userId - current user identifier
+ *
+ * @return string
+ */
+ private function buildUserId($userId) {
+ $instanceId = $this->config->GetSystemValue("instanceid", true);
+ $userId = $instanceId . "_" . $userId;
+ return $userId;
+ }
+
+ /**
+ * Return list users who has access to file
+ *
+ * @param File $file - file
+ *
+ * @return array
+ */
+ private function getAccessList($file) {
+ $result = [];
+
+ foreach ($this->shareManager->getSharesByPath($file) as $share) {
+ $accessList = [];
+ $shareWith = $share->getSharedWith();
+ if ($share->getShareType() === Share::SHARE_TYPE_GROUP) {
+ $group = $this->groupManager->get($shareWith);
+ $accessList = $group->getUsers();
+ } elseif ($share->getShareType() === Share::SHARE_TYPE_USER) {
+ array_push($accessList, $this->userManager->get($shareWith));
+ }
+
+ foreach ($accessList as $accessUser) {
+ if (!\in_array($accessUser, $result)) {
+ array_push($result, $accessUser);
+ }
+ }
+ }
+
+ if (!\in_array($file->getOwner(), $result)) {
+ array_push($result, $file->getOwner());
+ }
+
+ return $result;
+ }
+
+ /**
+ * Return allow autocomplete usernames
+ *
+ * @return bool
+ */
+ private function allowEnumeration() {
+ return \OC::$server->getConfig()->getAppValue("core", "shareapi_allow_share_dialog_user_enumeration", "yes") === "yes";
+ }
+
+ /**
+ * Return allow autocomplete usernames group member only
+ *
+ * @return bool
+ */
+ private function limitEnumerationToGroups() {
+ if ($this->allowEnumeration()) {
+ return \OC::$server->getConfig()->getAppValue("core", "shareapi_share_dialog_user_enumeration_group_members", "no") === "yes";
+ }
+
+ return false;
+ }
+
+ /**
+ * Print error page
+ *
+ * @param string $error - error message
+ * @param string $hint - error hint
+ *
+ * @return TemplateResponse
+ */
+ private function renderError($error, $hint = "") {
+ return new TemplateResponse("", "error", [
+ "errors" => [
+ [
+ "error" => $error,
+ "hint" => $hint
+ ]
+ ]
+ ], "error");
+ }
}
diff --git a/controller/federationcontroller.php b/controller/federationcontroller.php
index c4858ac0..5070fd5c 100644
--- a/controller/federationcontroller.php
+++ b/controller/federationcontroller.php
@@ -38,132 +38,132 @@
* OCS handler
*/
class FederationController extends OCSController {
- /**
- * Logger
- *
- * @var ILogger
- */
- private $logger;
-
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- public $config;
-
- /**
- * File utility
- *
- * @var FileUtility
- */
- private $fileUtility;
-
- /**
- * @param string $AppName - application name
- * @param IRequest $request - request object
- * @param IL10N $trans - l10n service
- * @param ILogger $logger - logger
- * @param IManager $shareManager - Share manager
- * @param IManager $ISession - Session
- */
- public function __construct(
- $AppName,
- IRequest $request,
- IL10N $trans,
- ILogger $logger,
- IManager $shareManager,
- ISession $session
- ) {
- parent::__construct($AppName, $request);
-
- $this->logger = $logger;
-
- $this->config = new AppConfig($this->appName);
- $this->fileUtility = new FileUtility($AppName, $trans, $logger, $this->config, $shareManager, $session);
- }
-
- /**
- * Returns the origin document key for editor
- *
- * @param string $shareToken - access token
- * @param string $path - file path
- *
- * @return Result
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- * @PublicPage
- */
- public function key($shareToken, $path) {
- list($file, $error, $share) = $this->fileUtility->getFileByToken(null, $shareToken, $path);
-
- if (isset($error)) {
- $this->logger->error("Federated getFileByToken: $error", ["app" => $this->appName]);
- return new Result(["error" => $error]);
- }
-
- $key = $this->fileUtility->getKey($file, true);
-
- $key = DocumentService::GenerateRevisionId($key);
-
- $this->logger->debug("Federated request get for " . $file->getId() . " key $key", ["app" => $this->appName]);
-
- return new Result(["key" => $key]);
- }
-
- /**
- * Lock the origin document key for editor
- *
- * @param string $shareToken - access token
- * @param string $path - file path
- * @param bool $lock - status
- * @param bool $fs - status
- *
- * @return Result
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- * @PublicPage
- */
- public function keylock($shareToken, $path, $lock, $fs) {
- list($file, $error, $share) = $this->fileUtility->getFileByToken(null, $shareToken, $path);
-
- if (isset($error)) {
- $this->logger->error("Federated getFileByToken: $error", ["app" => $this->appName]);
- return new Result(["error" => $error]);
- }
-
- $fileId = $file->getId();
-
- if (RemoteInstance::isRemoteFile($file)) {
- $isLock = RemoteInstance::lockRemoteKey($file, $lock, $fs);
- if (!$isLock) {
- return new Result(["error" => "Failed request"]);
- }
- } else {
- KeyManager::lock($fileId, $lock);
- if (!empty($fs)) {
- KeyManager::setForcesave($fileId, $fs);
- }
- }
-
- $this->logger->debug("Federated request lock for " . $fileId, ["app" => $this->appName]);
- return new Result();
- }
-
- /**
- * Health check instance
- *
- * @return Result
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- * @PublicPage
- */
- public function healthcheck() {
- $this->logger->debug("Federated healthcheck", ["app" => $this->appName]);
-
- return new Result(["alive" => true]);
- }
+ /**
+ * Logger
+ *
+ * @var ILogger
+ */
+ private $logger;
+
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ public $config;
+
+ /**
+ * File utility
+ *
+ * @var FileUtility
+ */
+ private $fileUtility;
+
+ /**
+ * @param string $AppName - application name
+ * @param IRequest $request - request object
+ * @param IL10N $trans - l10n service
+ * @param ILogger $logger - logger
+ * @param IManager $shareManager - Share manager
+ * @param IManager $ISession - Session
+ */
+ public function __construct(
+ $AppName,
+ IRequest $request,
+ IL10N $trans,
+ ILogger $logger,
+ IManager $shareManager,
+ ISession $session
+ ) {
+ parent::__construct($AppName, $request);
+
+ $this->logger = $logger;
+
+ $this->config = new AppConfig($this->appName);
+ $this->fileUtility = new FileUtility($AppName, $trans, $logger, $this->config, $shareManager, $session);
+ }
+
+ /**
+ * Returns the origin document key for editor
+ *
+ * @param string $shareToken - access token
+ * @param string $path - file path
+ *
+ * @return Result
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
+ */
+ public function key($shareToken, $path) {
+ list($file, $error, $share) = $this->fileUtility->getFileByToken(null, $shareToken, $path);
+
+ if (isset($error)) {
+ $this->logger->error("Federated getFileByToken: $error", ["app" => $this->appName]);
+ return new Result(["error" => $error]);
+ }
+
+ $key = $this->fileUtility->getKey($file, true);
+
+ $key = DocumentService::GenerateRevisionId($key);
+
+ $this->logger->debug("Federated request get for " . $file->getId() . " key $key", ["app" => $this->appName]);
+
+ return new Result(["key" => $key]);
+ }
+
+ /**
+ * Lock the origin document key for editor
+ *
+ * @param string $shareToken - access token
+ * @param string $path - file path
+ * @param bool $lock - status
+ * @param bool $fs - status
+ *
+ * @return Result
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
+ */
+ public function keylock($shareToken, $path, $lock, $fs) {
+ list($file, $error, $share) = $this->fileUtility->getFileByToken(null, $shareToken, $path);
+
+ if (isset($error)) {
+ $this->logger->error("Federated getFileByToken: $error", ["app" => $this->appName]);
+ return new Result(["error" => $error]);
+ }
+
+ $fileId = $file->getId();
+
+ if (RemoteInstance::isRemoteFile($file)) {
+ $isLock = RemoteInstance::lockRemoteKey($file, $lock, $fs);
+ if (!$isLock) {
+ return new Result(["error" => "Failed request"]);
+ }
+ } else {
+ KeyManager::lock($fileId, $lock);
+ if (!empty($fs)) {
+ KeyManager::setForcesave($fileId, $fs);
+ }
+ }
+
+ $this->logger->debug("Federated request lock for " . $fileId, ["app" => $this->appName]);
+ return new Result();
+ }
+
+ /**
+ * Health check instance
+ *
+ * @return Result
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
+ */
+ public function healthcheck() {
+ $this->logger->debug("Federated healthcheck", ["app" => $this->appName]);
+
+ return new Result(["alive" => true]);
+ }
}
diff --git a/controller/joblistcontroller.php b/controller/joblistcontroller.php
index a1138043..562eecdf 100644
--- a/controller/joblistcontroller.php
+++ b/controller/joblistcontroller.php
@@ -39,84 +39,84 @@
* @package OCA\Onlyoffice\Controller
*/
class JobListController extends Controller {
- /**
- * Logger
- *
- * @var ILogger
- */
- private $logger;
+ /**
+ * Logger
+ *
+ * @var ILogger
+ */
+ private $logger;
- /**
- * Job list
- *
- * @var IJobList
- */
- private $jobList;
+ /**
+ * Job list
+ *
+ * @var IJobList
+ */
+ private $jobList;
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- private $config;
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ private $config;
- /**
- * JobListController constructor.
- *
- * @param string $AppName - application name
- * @param IRequest $request - request object
- * @param ILogger $logger
- * @param AppConfig $config - application configuration
- * @param IJobList $jobList - job list
- */
- public function __construct($AppName, IRequest $request, ILogger $logger, AppConfig $config, IJobList $jobList) {
- parent::__construct($AppName, $request);
- $this->logger = $logger;
- $this->config = $config;
- $this->jobList = $jobList;
- }
+ /**
+ * JobListController constructor.
+ *
+ * @param string $AppName - application name
+ * @param IRequest $request - request object
+ * @param ILogger $logger
+ * @param AppConfig $config - application configuration
+ * @param IJobList $jobList - job list
+ */
+ public function __construct($AppName, IRequest $request, ILogger $logger, AppConfig $config, IJobList $jobList) {
+ parent::__construct($AppName, $request);
+ $this->logger = $logger;
+ $this->config = $config;
+ $this->jobList = $jobList;
+ }
- /**
- * Add a job to list
- *
- * @param IJob|string $job
- */
- private function addJob($job) {
- if (!$this->jobList->has($job, null)) {
- $this->jobList->add($job);
- $this->logger->debug("Job '".$job."' added to JobList.", ["app" => $this->appName]);
- }
- }
+ /**
+ * Add a job to list
+ *
+ * @param IJob|string $job
+ */
+ private function addJob($job) {
+ if (!$this->jobList->has($job, null)) {
+ $this->jobList->add($job);
+ $this->logger->debug("Job '".$job."' added to JobList.", ["app" => $this->appName]);
+ }
+ }
- /**
- * Remove a job from list
- *
- * @param IJob|string $job
- */
- private function removeJob($job) {
- if ($this->jobList->has($job, null)) {
- $this->jobList->remove($job);
- $this->logger->debug("Job '".$job."' removed from JobList.", ["app" => $this->appName]);
- }
- }
+ /**
+ * Remove a job from list
+ *
+ * @param IJob|string $job
+ */
+ private function removeJob($job) {
+ if ($this->jobList->has($job, null)) {
+ $this->jobList->remove($job);
+ $this->logger->debug("Job '".$job."' removed from JobList.", ["app" => $this->appName]);
+ }
+ }
- /**
- * Add or remove EditorsCheck job depending on the value of _editors_check_interval
- *
- */
- private function checkEditorsCheckJob() {
- if ($this->config->GetEditorsCheckInterval() > 0) {
- $this->addJob(EditorsCheck::class);
- } else {
- $this->removeJob(EditorsCheck::class);
- }
- }
+ /**
+ * Add or remove EditorsCheck job depending on the value of _editors_check_interval
+ *
+ */
+ private function checkEditorsCheckJob() {
+ if ($this->config->GetEditorsCheckInterval() > 0) {
+ $this->addJob(EditorsCheck::class);
+ } else {
+ $this->removeJob(EditorsCheck::class);
+ }
+ }
- /**
- * Method for sequentially calling checks of all jobs
- *
- */
- public function checkAllJobs() {
- $this->checkEditorsCheckJob();
- }
+ /**
+ * Method for sequentially calling checks of all jobs
+ *
+ */
+ public function checkAllJobs() {
+ $this->checkEditorsCheckJob();
+ }
}
diff --git a/controller/settingsapicontroller.php b/controller/settingsapicontroller.php
index 83e2f6e8..45369859 100644
--- a/controller/settingsapicontroller.php
+++ b/controller/settingsapicontroller.php
@@ -30,54 +30,54 @@
* Settings controller for the administration page
*/
class SettingsApiController extends OCSController {
- /**
- * Url generator service
- *
- * @var IURLGenerator
- */
- private $urlGenerator;
+ /**
+ * Url generator service
+ *
+ * @var IURLGenerator
+ */
+ private $urlGenerator;
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- private $config;
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ private $config;
- /**
- * @param string $AppName - application name
- * @param IRequest $request - request object
- * @param IURLGenerator $urlGenerator - url generator service
- * @param AppConfig $config - application configuration
- */
- public function __construct(
- $AppName,
- IRequest $request,
- IURLGenerator $urlGenerator,
- AppConfig $config
- ) {
- parent::__construct($AppName, $request);
+ /**
+ * @param string $AppName - application name
+ * @param IRequest $request - request object
+ * @param IURLGenerator $urlGenerator - url generator service
+ * @param AppConfig $config - application configuration
+ */
+ public function __construct(
+ $AppName,
+ IRequest $request,
+ IURLGenerator $urlGenerator,
+ AppConfig $config
+ ) {
+ parent::__construct($AppName, $request);
- $this->urlGenerator = $urlGenerator;
- $this->config = $config;
- }
+ $this->urlGenerator = $urlGenerator;
+ $this->config = $config;
+ }
- /**
- * Get document server url
- *
- * @return JSONResponse
- *
- * @NoAdminRequired
- * @CORS
- */
- public function GetDocServerUrl() {
- $url = $this->config->GetDocumentServerUrl();
- if (!$this->config->SettingsAreSuccessful()) {
- $url = "";
- } elseif (!preg_match("/^https?:\/\//i", $url)) {
- $url = $this->urlGenerator->getAbsoluteURL($url);
- }
+ /**
+ * Get document server url
+ *
+ * @return JSONResponse
+ *
+ * @NoAdminRequired
+ * @CORS
+ */
+ public function GetDocServerUrl() {
+ $url = $this->config->GetDocumentServerUrl();
+ if (!$this->config->SettingsAreSuccessful()) {
+ $url = "";
+ } elseif (!preg_match("/^https?:\/\//i", $url)) {
+ $url = $this->urlGenerator->getAbsoluteURL($url);
+ }
- return new JSONResponse(["documentServerUrl" => $url]);
- }
+ return new JSONResponse(["documentServerUrl" => $url]);
+ }
}
diff --git a/controller/settingscontroller.php b/controller/settingscontroller.php
index 4d3ba471..870b8675 100644
--- a/controller/settingscontroller.php
+++ b/controller/settingscontroller.php
@@ -36,292 +36,292 @@
* Settings controller for the administration page
*/
class SettingsController extends Controller {
- /**
- * l10n service
- *
- * @var IL10N
- */
- private $trans;
+ /**
+ * l10n service
+ *
+ * @var IL10N
+ */
+ private $trans;
- /**
- * Logger
- *
- * @var ILogger
- */
- private $logger;
+ /**
+ * Logger
+ *
+ * @var ILogger
+ */
+ private $logger;
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- private $config;
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ private $config;
- /**
- * Url generator service
- *
- * @var IURLGenerator
- */
- private $urlGenerator;
+ /**
+ * Url generator service
+ *
+ * @var IURLGenerator
+ */
+ private $urlGenerator;
- /**
- * Hash generator
- *
- * @var Crypt
- */
- private $crypt;
+ /**
+ * Hash generator
+ *
+ * @var Crypt
+ */
+ private $crypt;
- /**
- * @param string $AppName - application name
- * @param IRequest $request - request object
- * @param IURLGenerator $urlGenerator - url generator service
- * @param IL10N $trans - l10n service
- * @param ILogger $logger - logger
- * @param AppConfig $config - application configuration
- * @param Crypt $crypt - hash generator
- */
- public function __construct(
- $AppName,
- IRequest $request,
- IURLGenerator $urlGenerator,
- IL10N $trans,
- ILogger $logger,
- AppConfig $config,
- Crypt $crypt
- ) {
- parent::__construct($AppName, $request);
+ /**
+ * @param string $AppName - application name
+ * @param IRequest $request - request object
+ * @param IURLGenerator $urlGenerator - url generator service
+ * @param IL10N $trans - l10n service
+ * @param ILogger $logger - logger
+ * @param AppConfig $config - application configuration
+ * @param Crypt $crypt - hash generator
+ */
+ public function __construct(
+ $AppName,
+ IRequest $request,
+ IURLGenerator $urlGenerator,
+ IL10N $trans,
+ ILogger $logger,
+ AppConfig $config,
+ Crypt $crypt
+ ) {
+ parent::__construct($AppName, $request);
- $this->urlGenerator = $urlGenerator;
- $this->trans = $trans;
- $this->logger = $logger;
- $this->config = $config;
- $this->crypt = $crypt;
- }
+ $this->urlGenerator = $urlGenerator;
+ $this->trans = $trans;
+ $this->logger = $logger;
+ $this->config = $config;
+ $this->crypt = $crypt;
+ }
- /**
- * Print config section
- *
- * @return TemplateResponse
- */
- public function index() {
- $data = [
- "documentserver" => $this->config->GetDocumentServerUrl(true),
- "documentserverInternal" => $this->config->GetDocumentServerInternalUrl(true),
- "storageUrl" => $this->config->GetStorageUrl(),
- "verifyPeerOff" => $this->config->GetVerifyPeerOff(),
- "secret" => $this->config->GetDocumentServerSecret(true),
- "jwtHeader" => $this->config->JwtHeader(true),
- "demo" => $this->config->GetDemoData(),
- "currentServer" => $this->urlGenerator->getAbsoluteURL("/"),
- "formats" => $this->config->FormatsSetting(),
- "sameTab" => $this->config->GetSameTab(),
- "preview" => $this->config->GetPreview(),
- "versionHistory" => $this->config->GetVersionHistory(),
- "protection" => $this->config->GetProtection(),
- "encryption" => $this->config->checkEncryptionModule(),
- "limitGroups" => $this->config->GetLimitGroups(),
- "chat" => $this->config->GetCustomizationChat(),
- "compactHeader" => $this->config->GetCustomizationCompactHeader(),
- "feedback" => $this->config->GetCustomizationFeedback(),
- "forcesave" => $this->config->GetCustomizationForcesave(),
- "help" => $this->config->GetCustomizationHelp(),
- "toolbarNoTabs" => $this->config->GetCustomizationToolbarNoTabs(),
- "successful" => $this->config->SettingsAreSuccessful(),
- "plugins" => $this->config->GetCustomizationPlugins(),
- "macros" => $this->config->GetCustomizationMacros(),
- "reviewDisplay" => $this->config->GetCustomizationReviewDisplay(),
- "theme" => $this->config->GetCustomizationTheme(),
- "templates" => $this->GetGlobalTemplates(),
- "linkToDocs" => $this->config->GetLinkToDocs()
- ];
- return new TemplateResponse($this->appName, "settings", $data, "blank");
- }
+ /**
+ * Print config section
+ *
+ * @return TemplateResponse
+ */
+ public function index() {
+ $data = [
+ "documentserver" => $this->config->GetDocumentServerUrl(true),
+ "documentserverInternal" => $this->config->GetDocumentServerInternalUrl(true),
+ "storageUrl" => $this->config->GetStorageUrl(),
+ "verifyPeerOff" => $this->config->GetVerifyPeerOff(),
+ "secret" => $this->config->GetDocumentServerSecret(true),
+ "jwtHeader" => $this->config->JwtHeader(true),
+ "demo" => $this->config->GetDemoData(),
+ "currentServer" => $this->urlGenerator->getAbsoluteURL("/"),
+ "formats" => $this->config->FormatsSetting(),
+ "sameTab" => $this->config->GetSameTab(),
+ "preview" => $this->config->GetPreview(),
+ "versionHistory" => $this->config->GetVersionHistory(),
+ "protection" => $this->config->GetProtection(),
+ "encryption" => $this->config->checkEncryptionModule(),
+ "limitGroups" => $this->config->GetLimitGroups(),
+ "chat" => $this->config->GetCustomizationChat(),
+ "compactHeader" => $this->config->GetCustomizationCompactHeader(),
+ "feedback" => $this->config->GetCustomizationFeedback(),
+ "forcesave" => $this->config->GetCustomizationForcesave(),
+ "help" => $this->config->GetCustomizationHelp(),
+ "toolbarNoTabs" => $this->config->GetCustomizationToolbarNoTabs(),
+ "successful" => $this->config->SettingsAreSuccessful(),
+ "plugins" => $this->config->GetCustomizationPlugins(),
+ "macros" => $this->config->GetCustomizationMacros(),
+ "reviewDisplay" => $this->config->GetCustomizationReviewDisplay(),
+ "theme" => $this->config->GetCustomizationTheme(),
+ "templates" => $this->GetGlobalTemplates(),
+ "linkToDocs" => $this->config->GetLinkToDocs()
+ ];
+ return new TemplateResponse($this->appName, "settings", $data, "blank");
+ }
- /**
- * Save address settings
- *
- * @param string $jwtHeader - jwt header
- * @param string $documentserver - document service address
- * @param string $documentserverInternal - document service address available from ownCloud
- * @param string $storageUrl - ownCloud address available from document server
- * @param bool $verifyPeerOff - parameter verification setting
- * @param string $secret - secret key for signature
- * @param bool $demo - use demo server
- *
- * @return array
- */
- public function SaveAddress(
- $documentserver,
- $documentserverInternal,
- $storageUrl,
- $verifyPeerOff,
- $secret,
- $jwtHeader,
- $demo
- ) {
- $error = null;
- if (!$this->config->SelectDemo($demo === true)) {
- $error = $this->trans->t("The 30-day test period is over, you can no longer connect to demo ONLYOFFICE Docs server.");
- }
- if ($demo !== true) {
- $this->config->SetDocumentServerUrl($documentserver);
- $this->config->SetVerifyPeerOff($verifyPeerOff);
- $this->config->SetDocumentServerInternalUrl($documentserverInternal);
- $this->config->SetDocumentServerSecret($secret);
- $this->config->SetJwtHeader($jwtHeader);
- }
- $this->config->SetStorageUrl($storageUrl);
+ /**
+ * Save address settings
+ *
+ * @param string $jwtHeader - jwt header
+ * @param string $documentserver - document service address
+ * @param string $documentserverInternal - document service address available from ownCloud
+ * @param string $storageUrl - ownCloud address available from document server
+ * @param bool $verifyPeerOff - parameter verification setting
+ * @param string $secret - secret key for signature
+ * @param bool $demo - use demo server
+ *
+ * @return array
+ */
+ public function SaveAddress(
+ $documentserver,
+ $documentserverInternal,
+ $storageUrl,
+ $verifyPeerOff,
+ $secret,
+ $jwtHeader,
+ $demo
+ ) {
+ $error = null;
+ if (!$this->config->SelectDemo($demo === true)) {
+ $error = $this->trans->t("The 30-day test period is over, you can no longer connect to demo ONLYOFFICE Docs server.");
+ }
+ if ($demo !== true) {
+ $this->config->SetDocumentServerUrl($documentserver);
+ $this->config->SetVerifyPeerOff($verifyPeerOff);
+ $this->config->SetDocumentServerInternalUrl($documentserverInternal);
+ $this->config->SetDocumentServerSecret($secret);
+ $this->config->SetJwtHeader($jwtHeader);
+ }
+ $this->config->SetStorageUrl($storageUrl);
- $version = null;
- if (empty($error)) {
- $documentserver = $this->config->GetDocumentServerUrl();
- if (!empty($documentserver)) {
- $documentService = new DocumentService($this->trans, $this->config);
- list($error, $version) = $documentService->checkDocServiceUrl($this->urlGenerator, $this->crypt);
- $this->config->SetSettingsError($error);
- }
+ $version = null;
+ if (empty($error)) {
+ $documentserver = $this->config->GetDocumentServerUrl();
+ if (!empty($documentserver)) {
+ $documentService = new DocumentService($this->trans, $this->config);
+ list($error, $version) = $documentService->checkDocServiceUrl($this->urlGenerator, $this->crypt);
+ $this->config->SetSettingsError($error);
+ }
- if ($this->config->checkEncryptionModule() === true) {
- $this->logger->info("SaveSettings when encryption is enabled", ["app" => $this->appName]);
- }
- }
+ if ($this->config->checkEncryptionModule() === true) {
+ $this->logger->info("SaveSettings when encryption is enabled", ["app" => $this->appName]);
+ }
+ }
- return [
- "documentserver" => $this->config->GetDocumentServerUrl(true),
- "verifyPeerOff" => $this->config->GetVerifyPeerOff(),
- "documentserverInternal" => $this->config->GetDocumentServerInternalUrl(true),
- "storageUrl" => $this->config->GetStorageUrl(),
- "secret" => $this->config->GetDocumentServerSecret(true),
- "jwtHeader" => $this->config->JwtHeader(true),
- "error" => $error,
- "version" => $version,
- ];
- }
+ return [
+ "documentserver" => $this->config->GetDocumentServerUrl(true),
+ "verifyPeerOff" => $this->config->GetVerifyPeerOff(),
+ "documentserverInternal" => $this->config->GetDocumentServerInternalUrl(true),
+ "storageUrl" => $this->config->GetStorageUrl(),
+ "secret" => $this->config->GetDocumentServerSecret(true),
+ "jwtHeader" => $this->config->JwtHeader(true),
+ "error" => $error,
+ "version" => $version,
+ ];
+ }
- /**
- * Save common settings
- *
- * @param array $defFormats - formats array with default action
- * @param array $editFormats - editable formats array
- * @param bool $sameTab - open in the same tab
- * @param bool $preview - generate preview files
- * @param bool $versionHistory - keep version history
- * @param array $limitGroups - list of groups
- * @param bool $chat - display chat
- * @param bool $compactHeader - display compact header
- * @param bool $feedback - display feedback
- * @param bool $forcesave - forcesave
- * @param bool $help - display help
- * @param bool $toolbarNoTabs - display toolbar tab
- * @param string $reviewDisplay - review viewing mode
- * @param string $theme - default theme mode
- *
- * @return array
- */
- public function SaveCommon(
- $defFormats,
- $editFormats,
- $sameTab,
- $preview,
- $versionHistory,
- $limitGroups,
- $chat,
- $compactHeader,
- $feedback,
- $forcesave,
- $help,
- $toolbarNoTabs,
- $reviewDisplay,
- $theme
- ) {
- $this->config->SetDefaultFormats($defFormats);
- $this->config->SetEditableFormats($editFormats);
- $this->config->SetSameTab($sameTab);
- $this->config->SetPreview($preview);
- $this->config->SetVersionHistory($versionHistory);
- $this->config->SetLimitGroups($limitGroups);
- $this->config->SetCustomizationChat($chat);
- $this->config->SetCustomizationCompactHeader($compactHeader);
- $this->config->SetCustomizationFeedback($feedback);
- $this->config->SetCustomizationForcesave($forcesave);
- $this->config->SetCustomizationHelp($help);
- $this->config->SetCustomizationToolbarNoTabs($toolbarNoTabs);
- $this->config->SetCustomizationReviewDisplay($reviewDisplay);
- $this->config->SetCustomizationTheme($theme);
+ /**
+ * Save common settings
+ *
+ * @param array $defFormats - formats array with default action
+ * @param array $editFormats - editable formats array
+ * @param bool $sameTab - open in the same tab
+ * @param bool $preview - generate preview files
+ * @param bool $versionHistory - keep version history
+ * @param array $limitGroups - list of groups
+ * @param bool $chat - display chat
+ * @param bool $compactHeader - display compact header
+ * @param bool $feedback - display feedback
+ * @param bool $forcesave - forcesave
+ * @param bool $help - display help
+ * @param bool $toolbarNoTabs - display toolbar tab
+ * @param string $reviewDisplay - review viewing mode
+ * @param string $theme - default theme mode
+ *
+ * @return array
+ */
+ public function SaveCommon(
+ $defFormats,
+ $editFormats,
+ $sameTab,
+ $preview,
+ $versionHistory,
+ $limitGroups,
+ $chat,
+ $compactHeader,
+ $feedback,
+ $forcesave,
+ $help,
+ $toolbarNoTabs,
+ $reviewDisplay,
+ $theme
+ ) {
+ $this->config->SetDefaultFormats($defFormats);
+ $this->config->SetEditableFormats($editFormats);
+ $this->config->SetSameTab($sameTab);
+ $this->config->SetPreview($preview);
+ $this->config->SetVersionHistory($versionHistory);
+ $this->config->SetLimitGroups($limitGroups);
+ $this->config->SetCustomizationChat($chat);
+ $this->config->SetCustomizationCompactHeader($compactHeader);
+ $this->config->SetCustomizationFeedback($feedback);
+ $this->config->SetCustomizationForcesave($forcesave);
+ $this->config->SetCustomizationHelp($help);
+ $this->config->SetCustomizationToolbarNoTabs($toolbarNoTabs);
+ $this->config->SetCustomizationReviewDisplay($reviewDisplay);
+ $this->config->SetCustomizationTheme($theme);
- return [
- ];
- }
+ return [
+ ];
+ }
- /**
- * Save security settings
- *
- * @param bool $plugins - enable plugins
- * @param bool $macros - run document macros
- * @param string $protection - protection
- *
- * @return array
- */
- public function SaveSecurity(
- $plugins,
- $macros,
- $protection
- ) {
- $this->config->SetCustomizationPlugins($plugins);
- $this->config->SetCustomizationMacros($macros);
- $this->config->SetProtection($protection);
+ /**
+ * Save security settings
+ *
+ * @param bool $plugins - enable plugins
+ * @param bool $macros - run document macros
+ * @param string $protection - protection
+ *
+ * @return array
+ */
+ public function SaveSecurity(
+ $plugins,
+ $macros,
+ $protection
+ ) {
+ $this->config->SetCustomizationPlugins($plugins);
+ $this->config->SetCustomizationMacros($macros);
+ $this->config->SetProtection($protection);
- return [
- ];
- }
+ return [
+ ];
+ }
- /**
- * Clear all version history
- *
- * @return array
- */
- public function ClearHistory() {
- FileVersions::clearHistory();
+ /**
+ * Clear all version history
+ *
+ * @return array
+ */
+ public function ClearHistory() {
+ FileVersions::clearHistory();
- return [
- ];
- }
+ return [
+ ];
+ }
- /**
- * Get app settings
- *
- * @return array
- *
- * @NoAdminRequired
- * @PublicPage
- */
- public function GetSettings() {
- $result = [
- "formats" => $this->config->FormatsSetting(),
- "sameTab" => $this->config->GetSameTab(),
- "shareAttributesVersion" => $this->config->ShareAttributesVersion()
- ];
- return $result;
- }
+ /**
+ * Get app settings
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ * @PublicPage
+ */
+ public function GetSettings() {
+ $result = [
+ "formats" => $this->config->FormatsSetting(),
+ "sameTab" => $this->config->GetSameTab(),
+ "shareAttributesVersion" => $this->config->ShareAttributesVersion()
+ ];
+ return $result;
+ }
- /**
- * Get global templates
- *
- * @return array
- */
- private function GetGlobalTemplates() {
- $templates = [];
- $templatesList = TemplateManager::GetGlobalTemplates();
+ /**
+ * Get global templates
+ *
+ * @return array
+ */
+ private function GetGlobalTemplates() {
+ $templates = [];
+ $templatesList = TemplateManager::GetGlobalTemplates();
- foreach ($templatesList as $templateItem) {
- $template = [
- "id" => $templateItem->getId(),
- "name" => $templateItem->getName(),
- "type" => TemplateManager::GetTypeTemplate($templateItem->getMimeType())
- ];
- array_push($templates, $template);
- }
+ foreach ($templatesList as $templateItem) {
+ $template = [
+ "id" => $templateItem->getId(),
+ "name" => $templateItem->getName(),
+ "type" => TemplateManager::GetTypeTemplate($templateItem->getMimeType())
+ ];
+ array_push($templates, $template);
+ }
- return $templates;
- }
+ return $templates;
+ }
}
diff --git a/controller/templatecontroller.php b/controller/templatecontroller.php
index 98aa3da3..4dfc1317 100644
--- a/controller/templatecontroller.php
+++ b/controller/templatecontroller.php
@@ -30,132 +30,132 @@
* Template controller for template manage
*/
class TemplateController extends Controller {
- /**
- * l10n service
- *
- * @var IL10N
- */
- private $trans;
-
- /**
- * Logger
- *
- * @var ILogger
- */
- private $logger;
-
- /**
- * @param string $AppName - application name
- * @param IRequest $request - request object
- * @param IL10N $trans - l10n service
- */
- public function __construct(
- $AppName,
- IRequest $request,
- IL10N $trans,
- ILogger $logger
- ) {
- parent::__construct($AppName, $request);
-
- $this->trans = $trans;
- $this->logger = $logger;
- }
-
- /**
- * Get templates
- *
- * @return array
- *
- * @NoAdminRequired
- */
- public function GetTemplates() {
- $templatesList = TemplateManager::GetGlobalTemplates();
-
- $templates = [];
- foreach ($templatesList as $templatesItem) {
- $template = [
- "id" => $templatesItem->getId(),
- "name" => $templatesItem->getName(),
- "type" => TemplateManager::GetTypeTemplate($templatesItem->getMimeType())
- ];
- array_push($templates, $template);
- }
-
- return $templates;
- }
-
- /**
- * Add global template
- *
- * @return array
- */
- public function AddTemplate() {
- $file = $this->request->getUploadedFile("file");
-
- if ($file !== null) {
- if (is_uploaded_file($file["tmp_name"]) && $file["error"] === 0) {
- if (!TemplateManager::IsTemplateType($file["name"])) {
- return [
- "error" => $this->trans->t("Template must be in OOXML format")
- ];
- }
-
- $templateDir = TemplateManager::GetGlobalTemplateDir();
- if ($templateDir->nodeExists($file["name"])) {
- return [
- "error" => $this->trans->t("Template already exists")
- ];
- }
-
- $templateContent = file_get_contents($file["tmp_name"]);
- $template = $templateDir->newFile($file["name"]);
- $template->putContent($templateContent);
-
- $fileInfo = $template->getFileInfo();
- $result = [
- "id" => $fileInfo->getId(),
- "name" => $fileInfo->getName(),
- "type" => TemplateManager::GetTypeTemplate($fileInfo->getMimeType())
- ];
-
- $this->logger->debug("Template: added " . $fileInfo->getName(), ["app" => $this->appName]);
-
- return $result;
- }
- }
-
- return [
- "error" => $this->trans->t("Invalid file provided")
- ];
- }
-
- /**
- * Delete template
- *
- * @param string $templateId - file identifier
- */
- public function DeleteTemplate($templateId) {
- $templateDir = TemplateManager::GetGlobalTemplateDir();
-
- try {
- $templates = $templateDir->getById($templateId);
- } catch(\Exception $e) {
- $this->logger->logException($e, ["message" => "DeleteTemplate: $templateId", "app" => $this->AppName]);
- return [
- "error" => $this->trans->t("Failed to delete template")
- ];
- }
-
- if (empty($templates)) {
- $this->logger->info("Template not found: $templateId", ["app" => $this->AppName]);
- return [
- "error" => $this->trans->t("Failed to delete template")
- ];
- }
-
- $templates[0]->delete();
-
- $this->logger->debug("Template: deleted " . $templates[0]->getName(), ["app" => $this->appName]);
- return [];
- }
+ /**
+ * l10n service
+ *
+ * @var IL10N
+ */
+ private $trans;
+
+ /**
+ * Logger
+ *
+ * @var ILogger
+ */
+ private $logger;
+
+ /**
+ * @param string $AppName - application name
+ * @param IRequest $request - request object
+ * @param IL10N $trans - l10n service
+ */
+ public function __construct(
+ $AppName,
+ IRequest $request,
+ IL10N $trans,
+ ILogger $logger
+ ) {
+ parent::__construct($AppName, $request);
+
+ $this->trans = $trans;
+ $this->logger = $logger;
+ }
+
+ /**
+ * Get templates
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ */
+ public function GetTemplates() {
+ $templatesList = TemplateManager::GetGlobalTemplates();
+
+ $templates = [];
+ foreach ($templatesList as $templatesItem) {
+ $template = [
+ "id" => $templatesItem->getId(),
+ "name" => $templatesItem->getName(),
+ "type" => TemplateManager::GetTypeTemplate($templatesItem->getMimeType())
+ ];
+ array_push($templates, $template);
+ }
+
+ return $templates;
+ }
+
+ /**
+ * Add global template
+ *
+ * @return array
+ */
+ public function AddTemplate() {
+ $file = $this->request->getUploadedFile("file");
+
+ if ($file !== null) {
+ if (is_uploaded_file($file["tmp_name"]) && $file["error"] === 0) {
+ if (!TemplateManager::IsTemplateType($file["name"])) {
+ return [
+ "error" => $this->trans->t("Template must be in OOXML format")
+ ];
+ }
+
+ $templateDir = TemplateManager::GetGlobalTemplateDir();
+ if ($templateDir->nodeExists($file["name"])) {
+ return [
+ "error" => $this->trans->t("Template already exists")
+ ];
+ }
+
+ $templateContent = file_get_contents($file["tmp_name"]);
+ $template = $templateDir->newFile($file["name"]);
+ $template->putContent($templateContent);
+
+ $fileInfo = $template->getFileInfo();
+ $result = [
+ "id" => $fileInfo->getId(),
+ "name" => $fileInfo->getName(),
+ "type" => TemplateManager::GetTypeTemplate($fileInfo->getMimeType())
+ ];
+
+ $this->logger->debug("Template: added " . $fileInfo->getName(), ["app" => $this->appName]);
+
+ return $result;
+ }
+ }
+
+ return [
+ "error" => $this->trans->t("Invalid file provided")
+ ];
+ }
+
+ /**
+ * Delete template
+ *
+ * @param string $templateId - file identifier
+ */
+ public function DeleteTemplate($templateId) {
+ $templateDir = TemplateManager::GetGlobalTemplateDir();
+
+ try {
+ $templates = $templateDir->getById($templateId);
+ } catch(\Exception $e) {
+ $this->logger->logException($e, ["message" => "DeleteTemplate: $templateId", "app" => $this->AppName]);
+ return [
+ "error" => $this->trans->t("Failed to delete template")
+ ];
+ }
+
+ if (empty($templates)) {
+ $this->logger->info("Template not found: $templateId", ["app" => $this->AppName]);
+ return [
+ "error" => $this->trans->t("Failed to delete template")
+ ];
+ }
+
+ $templates[0]->delete();
+
+ $this->logger->debug("Template: deleted " . $templates[0]->getName(), ["app" => $this->appName]);
+ return [];
+ }
}
diff --git a/controller/webassetcontroller.php b/controller/webassetcontroller.php
index 3e03ab7f..c904fbb2 100644
--- a/controller/webassetcontroller.php
+++ b/controller/webassetcontroller.php
@@ -33,46 +33,46 @@
* @package OCA\Onlyoffice\Controller
*/
class WebAssetController extends Controller {
- /**
- * @var ILogger
- */
- private $logger;
+ /**
+ * @var ILogger
+ */
+ private $logger;
- /**
- * WebAssetController constructor.
- *
- * @param string $AppName - application name
- * @param IRequest $request - request object
- * @param ILogger $logger
- */
- public function __construct($AppName, IRequest $request, ILogger $logger) {
- parent::__construct($AppName, $request);
- $this->logger = $logger;
- }
+ /**
+ * WebAssetController constructor.
+ *
+ * @param string $AppName - application name
+ * @param IRequest $request - request object
+ * @param ILogger $logger
+ */
+ public function __construct($AppName, IRequest $request, ILogger $logger) {
+ parent::__construct($AppName, $request);
+ $this->logger = $logger;
+ }
- /**
- * Loads the onlyoffice.js file for integration into ownCloud Web
- *
- * @PublicPage
- * @NoCSRFRequired
- *
- * @return Response
- */
- public function get(): Response {
- $basePath = \dirname(__DIR__, 1);
- $filePath = \realpath($basePath . '/js/web/onlyoffice.js');
- try {
- return new DataDisplayResponse(\file_get_contents($filePath), Http::STATUS_OK, [
- 'Content-Type' => "text/javascript",
- 'Content-Length' => \filesize($filePath),
- 'Cache-Control' => 'max-age=0, no-cache, no-store, must-revalidate',
- 'Pragma' => 'no-cache',
- 'Expires' => 'Tue, 24 Sep 1985 22:15:00 GMT',
- 'X-Frame-Options' => 'DENY'
- ]);
- } catch(\Exception $e) {
- $this->logger->logException($e, ['app' => $this->appName]);
- return new DataResponse(["message" => $e->getMessage()], Http::STATUS_NOT_FOUND);
- }
- }
+ /**
+ * Loads the onlyoffice.js file for integration into ownCloud Web
+ *
+ * @PublicPage
+ * @NoCSRFRequired
+ *
+ * @return Response
+ */
+ public function get(): Response {
+ $basePath = \dirname(__DIR__, 1);
+ $filePath = \realpath($basePath . '/js/web/onlyoffice.js');
+ try {
+ return new DataDisplayResponse(\file_get_contents($filePath), Http::STATUS_OK, [
+ 'Content-Type' => "text/javascript",
+ 'Content-Length' => \filesize($filePath),
+ 'Cache-Control' => 'max-age=0, no-cache, no-store, must-revalidate',
+ 'Pragma' => 'no-cache',
+ 'Expires' => 'Tue, 24 Sep 1985 22:15:00 GMT',
+ 'X-Frame-Options' => 'DENY'
+ ]);
+ } catch(\Exception $e) {
+ $this->logger->logException($e, ['app' => $this->appName]);
+ return new DataResponse(["message" => $e->getMessage()], Http::STATUS_NOT_FOUND);
+ }
+ }
}
diff --git a/lib/adminsettings.php b/lib/adminsettings.php
index 79b68135..14171bc4 100644
--- a/lib/adminsettings.php
+++ b/lib/adminsettings.php
@@ -25,33 +25,33 @@
* Settings controller for the administration page
*/
class AdminSettings implements ISettings {
- public function __construct() {
- }
+ public function __construct() {
+ }
- /**
- * Print config section
- *
- * @return TemplateResponse
- */
- public function getPanel() {
- return $this->getForm();
- }
+ /**
+ * Print config section
+ *
+ * @return TemplateResponse
+ */
+ public function getPanel() {
+ return $this->getForm();
+ }
- /**
- * Get section ID
- *
- * @return string
- */
- public function getSectionID() {
- return "general";
- }
+ /**
+ * Get section ID
+ *
+ * @return string
+ */
+ public function getSectionID() {
+ return "general";
+ }
- /**
- * Get priority order
- *
- * @return int
- */
- public function getPriority() {
- return 50;
- }
+ /**
+ * Get priority order
+ *
+ * @return int
+ */
+ public function getPriority() {
+ return 50;
+ }
}
diff --git a/lib/appconfig.php b/lib/appconfig.php
index ddbe49f1..8dac94f2 100644
--- a/lib/appconfig.php
+++ b/lib/appconfig.php
@@ -31,1231 +31,1231 @@
* @package OCA\Onlyoffice
*/
class AppConfig {
- /**
- * Application name
- *
- * @var string
- */
- private $appName;
-
- /**
- * Config service
- *
- * @var IConfig
- */
- private $config;
-
- /**
- * Logger
- *
- * @var ILogger
- */
- private $logger;
-
- /**
- * The config key for the demo server
- *
- * @var string
- */
- private $_demo = "demo";
-
- /**
- * The config key for the document server address
- *
- * @var string
- */
- private $_documentserver = "DocumentServerUrl";
-
- /**
- * The config key for the document server address available from ownCloud
- *
- * @var string
- */
- private $_documentserverInternal = "DocumentServerInternalUrl";
-
- /**
- * The config key for the ownCloud address available from document server
- *
- * @var string
- */
- private $_storageUrl = "StorageUrl";
-
- /**
- * The config key for the secret key
- *
- * @var string
- */
- private $_cryptSecret = "secret";
-
- /**
- * The config key for the default formats
- *
- * @var string
- */
- private $_defFormats = "defFormats";
-
- /**
- * The config key for the editable formats
- *
- * @var string
- */
- private $_editFormats = "editFormats";
-
- /**
- * The config key for the setting same tab
- *
- * @var string
- */
- private $_sameTab = "sameTab";
-
- /**
- * The config key for the generate preview
- *
- * @var string
- */
- private $_preview = "preview";
-
- /**
- * The config key for the keep versions history
- *
- * @var string
- */
- private $_versionHistory = "versionHistory";
-
- /**
- * The config key for the protection
- *
- * @var string
- */
- private $_protection = "protection";
-
- /**
- * The config key for the chat display setting
- *
- * @var string
- */
- private $_customizationChat = "customizationChat";
-
- /**
- * The config key for display the header more compact setting
- *
- * @var string
- */
- private $_customizationCompactHeader = "customizationCompactHeader";
-
- /**
- * The config key for the feedback display setting
- *
- * @var string
- */
- private $_customizationFeedback = "customizationFeedback";
-
- /**
- * The config key for the forcesave setting
- *
- * @var string
- */
- private $_customizationForcesave = "customizationForcesave";
-
- /**
- * The config key for the help display setting
- *
- * @var string
- */
- private $_customizationHelp = "customizationHelp";
-
- /**
- * The config key for the no tabs setting
- *
- * @var string
- */
- private $_customizationToolbarNoTabs = "customizationToolbarNoTabs";
-
- /**
- * The config key for the review mode setting
- *
- * @var string
- */
- private $_customizationReviewDisplay = "customizationReviewDisplay";
-
- /**
- * The config key for the theme setting
- *
- * @var string
- */
- private $_customizationTheme = "customizationTheme";
-
- /**
- * The config key for the setting limit groups
- *
- * @var string
- */
- private $_groups = "groups";
-
- /**
- * The config key for the verification
- *
- * @var string
- */
- private $_verification = "verify_peer_off";
-
- /**
- * The config key for the secret key in jwt
- *
- * @var string
- */
- private $_jwtSecret = "jwt_secret";
-
- /**
- * The config key for the jwt header
- *
- * @var string
- */
- private $_jwtHeader = "jwt_header";
-
- /**
- * The config key for the allowable leeway in Jwt checks
- *
- * @var string
- */
- private $_jwtLeeway = "jwt_leeway";
-
- /**
- * The config key for the settings error
- *
- * @var string
- */
- private $_settingsError = "settings_error";
-
- /**
- * The config key for limit thumbnail size
- *
- * @var string
- */
- public $_limitThumbSize = "limit_thumb_size";
-
- /**
- * The config key for the customer
- *
- * @var string
- */
- public $_customization_customer = "customization_customer";
-
- /**
- * The config key for the loaderLogo
- *
- * @var string
- */
- public $_customization_loaderLogo = "customization_loaderLogo";
-
- /**
- * The config key for the loaderName
- *
- * @var string
- */
- public $_customization_loaderName = "customization_loaderName";
-
- /**
- * The config key for the logo
- *
- * @var string
- */
- 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";
-
- /**
- * The config key for the goback
- *
- * @var string
- */
- public $_customization_goback = "customization_goback";
-
- /**
- * The config key for the macros
- *
- * @var string
- */
- public $_customization_macros = "customization_macros";
-
- /**
- * The config key for the plugins
- *
- * @var string
- */
- public $_customizationPlugins = "customization_plugins";
-
- /**
- * The config key for the interval of editors availability check by cron
- *
- * @var string
- */
- private $_editors_check_interval = "editors_check_interval";
-
- /**
- * @param string $AppName - application name
- */
- public function __construct($AppName) {
- $this->appName = $AppName;
-
- $this->config = \OC::$server->getConfig();
- $this->logger = \OC::$server->getLogger();
- }
-
- /**
- * Get value from the system configuration
- *
- * @param string $key - key configuration
- * @param bool $system - get from root or from app section
- *
- * @return string
- */
- public function GetSystemValue($key, $system = false) {
- if ($system) {
- return $this->config->getSystemValue($key);
- }
- if (!empty($this->config->getSystemValue($this->appName))
- && \array_key_exists($key, $this->config->getSystemValue($this->appName))) {
- return $this->config->getSystemValue($this->appName)[$key];
- }
- return null;
- }
-
- /**
- * Switch on demo server
- *
- * @param bool $value - select demo
- *
- * @return bool
- */
- public function SelectDemo($value) {
- $this->logger->info("Select demo: " . json_encode($value), ["app" => $this->appName]);
-
- $data = $this->GetDemoData();
-
- if ($value === true && !$data["available"]) {
- $this->logger->info("Trial demo is overdue: " . json_encode($data), ["app" => $this->appName]);
- return false;
- }
-
- $data["enabled"] = $value === true;
- if (!isset($data["start"])) {
- $data["start"] = new DateTime();
- }
-
- $this->config->setAppValue($this->appName, $this->_demo, json_encode($data));
- return true;
- }
-
- /**
- * Get demo data
- *
- * @return array
- */
- public function GetDemoData() {
- $data = $this->config->getAppValue($this->appName, $this->_demo, "");
-
- if (empty($data)) {
- return [
- "available" => true,
- "enabled" => false
- ];
- }
- $data = json_decode($data, true);
-
- $overdue = new DateTime(isset($data["start"]) ? $data["start"]["date"] : null);
- $overdue->add(new DateInterval("P" . $this->DEMO_PARAM["TRIAL"] . "D"));
- if ($overdue > new DateTime()) {
- $data["available"] = true;
- $data["enabled"] = $data["enabled"] === true;
- } else {
- $data["available"] = false;
- $data["enabled"] = false;
- }
-
- return $data;
- }
-
- /**
- * Get status of demo server
- *
- * @return bool
- */
- public function UseDemo() {
- return $this->GetDemoData()["enabled"] === true;
- }
-
- /**
- * Save the document service address to the application configuration
- *
- * @param string $documentServer - document service address
- */
- public function SetDocumentServerUrl($documentServer) {
- $documentServer = trim($documentServer);
- if (\strlen($documentServer) > 0) {
- $documentServer = rtrim($documentServer, "/") . "/";
- if (!preg_match("/(^https?:\/\/)|^\//i", $documentServer)) {
- $documentServer = "http://" . $documentServer;
- }
- }
-
- $this->logger->info("SetDocumentServerUrl: $documentServer", ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_documentserver, $documentServer);
- }
-
- /**
- * Get the document service address from the application configuration
- *
- * @param bool $origin - take origin
- *
- * @return string
- */
- public function GetDocumentServerUrl($origin = false) {
- if (!$origin && $this->UseDemo()) {
- return $this->DEMO_PARAM["ADDR"];
- }
-
- $url = $this->config->getAppValue($this->appName, $this->_documentserver, "");
- if (empty($url)) {
- $url = $this->GetSystemValue($this->_documentserver);
- }
- if ($url !== "/") {
- $url = rtrim($url, "/");
- if (\strlen($url) > 0) {
- $url = $url . "/";
- }
- }
- return $url;
- }
-
- /**
- * Save the document service address available from ownCloud to the application configuration
- *
- * @param string $documentServerInternal - document service address
- */
- public function SetDocumentServerInternalUrl($documentServerInternal) {
- $documentServerInternal = rtrim(trim($documentServerInternal), "/");
- if (\strlen($documentServerInternal) > 0) {
- $documentServerInternal = $documentServerInternal . "/";
- if (!preg_match("/^https?:\/\//i", $documentServerInternal)) {
- $documentServerInternal = "http://" . $documentServerInternal;
- }
- }
-
- $this->logger->info("SetDocumentServerInternalUrl: $documentServerInternal", ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_documentserverInternal, $documentServerInternal);
- }
-
- /**
- * Get the document service address available from ownCloud from the application configuration
- *
- * @param bool $origin - take origin
- *
- * @return string
- */
- public function GetDocumentServerInternalUrl($origin = false) {
- if (!$origin && $this->UseDemo()) {
- return $this->GetDocumentServerUrl();
- }
-
- $url = $this->config->getAppValue($this->appName, $this->_documentserverInternal, "");
- if (empty($url)) {
- $url = $this->GetSystemValue($this->_documentserverInternal);
- }
- if (!$origin && empty($url)) {
- $url = $this->GetDocumentServerUrl();
- }
- return $url;
- }
-
- /**
- * Replace domain in document server url with internal address from configuration
- *
- * @param string $url - document server url
- *
- * @return string
- */
- public function ReplaceDocumentServerUrlToInternal($url) {
- $documentServerUrl = $this->GetDocumentServerInternalUrl();
- if (!empty($documentServerUrl)) {
- $from = $this->GetDocumentServerUrl();
-
- if (!preg_match("/^https?:\/\//i", $from)) {
- $parsedUrl = parse_url($url);
- $from = $parsedUrl["scheme"] . "://" . $parsedUrl["host"] . (\array_key_exists("port", $parsedUrl) ? (":" . $parsedUrl["port"]) : "") . $from;
- }
-
- if ($from !== $documentServerUrl) {
- $this->logger->debug("Replace url from $from to $documentServerUrl", ["app" => $this->appName]);
- $url = str_replace($from, $documentServerUrl, $url);
- }
- }
-
- return $url;
- }
-
- /**
- * Save the ownCloud address available from document server to the application configuration
- *
- * @param string $documentServer - document service address
- */
- public function SetStorageUrl($storageUrl) {
- $storageUrl = rtrim(trim($storageUrl), "/");
- if (\strlen($storageUrl) > 0) {
- $storageUrl = $storageUrl . "/";
- if (!preg_match("/^https?:\/\//i", $storageUrl)) {
- $storageUrl = "http://" . $storageUrl;
- }
- }
-
- $this->logger->info("SetStorageUrl: $storageUrl", ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_storageUrl, $storageUrl);
- }
-
- /**
- * Get the ownCloud address available from document server from the application configuration
- *
- * @return string
- */
- public function GetStorageUrl() {
- $url = $this->config->getAppValue($this->appName, $this->_storageUrl, "");
- if (empty($url)) {
- $url = $this->GetSystemValue($this->_storageUrl);
- }
- return $url;
- }
-
- /**
- * Save the document service secret key to the application configuration
- *
- * @param string $secret - secret key
- */
- public function SetDocumentServerSecret($secret) {
- $secret = trim($secret);
- if (empty($secret)) {
- $this->logger->info("Clear secret key", ["app" => $this->appName]);
- } else {
- $this->logger->info("Set secret key", ["app" => $this->appName]);
- }
-
- $this->config->setAppValue($this->appName, $this->_jwtSecret, $secret);
- }
-
- /**
- * Get the document service secret key from the application configuration
- *
- * @param bool $origin - take origin
- *
- * @return string
- */
- public function GetDocumentServerSecret($origin = false) {
- if (!$origin && $this->UseDemo()) {
- return $this->DEMO_PARAM["SECRET"];
- }
-
- $secret = $this->config->getAppValue($this->appName, $this->_jwtSecret, "");
- if (empty($secret)) {
- $secret = $this->GetSystemValue($this->_jwtSecret);
- }
- return $secret;
- }
-
- /**
- * Get the secret key from the application configuration
- *
- * @return string
- */
- public function GetSKey() {
- $secret = $this->GetDocumentServerSecret();
- if (empty($secret)) {
- $secret = $this->GetSystemValue($this->_cryptSecret, true);
- }
- return $secret;
- }
-
- /**
- * Save an array of formats with default action
- *
- * @param array $formats - formats with status
- */
- public function SetDefaultFormats($formats) {
- $value = json_encode($formats);
- $this->logger->info("Set default formats: $value", ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_defFormats, $value);
- }
-
- /**
- * Get an array of formats with default action
- *
- * @return array
- */
- private function GetDefaultFormats() {
- $value = $this->config->getAppValue($this->appName, $this->_defFormats, "");
- if (empty($value)) {
- return [];
- }
- return json_decode($value, true);
- }
-
- /**
- * Save an array of formats that is opened for editing
- *
- * @param array $formats - formats with status
- */
- public function SetEditableFormats($formats) {
- $value = json_encode($formats);
- $this->logger->info("Set editing formats: $value", ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_editFormats, $value);
- }
-
- /**
- * Get an array of formats opening for editing
- *
- * @return array
- */
- private function GetEditableFormats() {
- $value = $this->config->getAppValue($this->appName, $this->_editFormats, "");
- if (empty($value)) {
- return [];
- }
- return json_decode($value, true);
- }
-
- /**
- * Save the opening setting in a same tab
- *
- * @param bool $value - same tab
- */
- public function SetSameTab($value) {
- $this->logger->info("Set opening in a same tab: " . json_encode($value), ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_sameTab, json_encode($value));
- }
-
- /**
- * Get the opening setting in a same tab
- *
- * @return bool
- */
- public function GetSameTab() {
- return $this->config->getAppValue($this->appName, $this->_sameTab, "false") === "true";
- }
-
- /**
- * Save generate preview setting
- *
- * @param bool $value - preview
- */
- public function SetPreview($value) {
- $this->logger->info("Set generate preview: " . json_encode($value), ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_preview, json_encode($value));
- }
-
- /**
- * Get generate preview setting
- *
- * @return bool
- */
- public function GetPreview() {
- return $this->config->getAppValue($this->appName, $this->_preview, "true") === "true";
- }
-
- /**
- * Save keep versions history
- *
- * @param bool $value - version history
- */
- public function SetVersionHistory($value) {
- $this->logger->info("Set keep versions history: " . json_encode($value), ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_versionHistory, json_encode($value));
- }
-
- /**
- * Get keep versions history
- *
- * @return bool
- */
- public function GetVersionHistory() {
- return $this->config->getAppValue($this->appName, $this->_versionHistory, "true") === "true";
- }
-
- /**
- * Save protection
- *
- * @param bool $value - version history
- */
- public function SetProtection($value) {
- $this->logger->info("Set protection: " . $value, ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_protection, $value);
- }
-
- /**
- * Get protection
- *
- * @return bool
- */
- public function GetProtection() {
- $value = $this->config->getAppValue($this->appName, $this->_protection, "owner");
- if ($value === "all") {
- return "all";
- }
- return "owner";
- }
-
- /**
- * Save chat display setting
- *
- * @param bool $value - display chat
- */
- public function SetCustomizationChat($value) {
- $this->logger->info("Set chat display: " . json_encode($value), ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_customizationChat, json_encode($value));
- }
-
- /**
- * Get chat display setting
- *
- * @return bool
- */
- public function GetCustomizationChat() {
- return $this->config->getAppValue($this->appName, $this->_customizationChat, "true") === "true";
- }
-
- /**
- * Save compact header setting
- *
- * @param bool $value - display compact header
- */
- public function SetCustomizationCompactHeader($value) {
- $this->logger->info("Set compact header display: " . json_encode($value), ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_customizationCompactHeader, json_encode($value));
- }
-
- /**
- * Get compact header setting
- *
- * @return bool
- */
- public function GetCustomizationCompactHeader() {
- return $this->config->getAppValue($this->appName, $this->_customizationCompactHeader, "true") === "true";
- }
-
- /**
- * Save feedback display setting
- *
- * @param bool $value - display feedback
- */
- public function SetCustomizationFeedback($value) {
- $this->logger->info("Set feedback display: " . json_encode($value), ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_customizationFeedback, json_encode($value));
- }
-
- /**
- * Get feedback display setting
- *
- * @return bool
- */
- public function GetCustomizationFeedback() {
- return $this->config->getAppValue($this->appName, $this->_customizationFeedback, "true") === "true";
- }
-
- /**
- * Save forcesave setting
- *
- * @param bool $value - forcesave
- */
- public function SetCustomizationForcesave($value) {
- $this->logger->info("Set forcesave: " . json_encode($value), ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_customizationForcesave, json_encode($value));
- }
-
- /**
- * Get forcesave setting
- *
- * @return bool
- */
- public function GetCustomizationForcesave() {
- $value = $this->config->getAppValue($this->appName, $this->_customizationForcesave, "false") === "true";
-
- return $value && ($this->checkEncryptionModule() === false);
- }
-
- /**
- * Save help display setting
- *
- * @param bool $value - display help
- */
- public function SetCustomizationHelp($value) {
- $this->logger->info("Set help display: " . json_encode($value), ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_customizationHelp, json_encode($value));
- }
-
- /**
- * Get help display setting
- *
- * @return bool
- */
- public function GetCustomizationHelp() {
- return $this->config->getAppValue($this->appName, $this->_customizationHelp, "true") === "true";
- }
-
- /**
- * Save without tabs setting
- *
- * @param bool $value - without tabs
- */
- public function SetCustomizationToolbarNoTabs($value) {
- $this->logger->info("Set without tabs: " . json_encode($value), ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_customizationToolbarNoTabs, json_encode($value));
- }
-
- /**
- * Get without tabs setting
- *
- * @return bool
- */
- public function GetCustomizationToolbarNoTabs() {
- return $this->config->getAppValue($this->appName, $this->_customizationToolbarNoTabs, "true") === "true";
- }
-
- /**
- * Save review viewing mode setting
- *
- * @param string $value - review mode
- */
- public function SetCustomizationReviewDisplay($value) {
- $this->logger->info("Set review mode: " . $value, ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_customizationReviewDisplay, $value);
- }
-
- /**
- * Get review viewing mode setting
- *
- * @return string
- */
- public function GetCustomizationReviewDisplay() {
- $value = $this->config->getAppValue($this->appName, $this->_customizationReviewDisplay, "original");
- if ($value === "markup") {
- return "markup";
- }
- if ($value === "final") {
- return "final";
- }
- return "original";
- }
-
- /**
- * Save theme setting
- *
- * @param string $value - theme
- */
- public function SetCustomizationTheme($value) {
- $this->logger->info("Set theme: " . $value, ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_customizationTheme, $value);
- }
-
- /**
- * Get theme setting
- *
- * @return string
- */
- public function GetCustomizationTheme() {
- $value = $this->config->getAppValue($this->appName, $this->_customizationTheme, "theme-classic-light");
- if ($value === "theme-light") {
- return "theme-light";
- }
- if ($value === "theme-dark") {
- return "theme-dark";
- }
- return "theme-classic-light";
- }
-
- /**
- * Save macros setting
- *
- * @param bool $value - enable macros
- */
- public function SetCustomizationMacros($value) {
- $this->logger->info("Set macros enabled: " . json_encode($value), ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_customization_macros, json_encode($value));
- }
-
- /**
- * Get macros setting
- *
- * @return bool
- */
- public function GetCustomizationMacros() {
- return $this->config->getAppValue($this->appName, $this->_customization_macros, "true") === "true";
- }
-
- /**
- * Save plugins setting
- *
- * @param bool $value - enable macros
- */
- public function SetCustomizationPlugins($value) {
- $this->logger->info("Set plugins enabled: " . json_encode($value), ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_customizationPlugins, json_encode($value));
- }
-
- /**
- * Get plugins setting
- *
- * @return bool
- */
- public function GetCustomizationPlugins() {
- return $this->config->getAppValue($this->appName, $this->_customizationPlugins, "true") === "true";
- }
-
- /**
- * Save the list of groups
- *
- * @param array $groups - the list of groups
- */
- public function SetLimitGroups($groups) {
- if (!\is_array($groups)) {
- $groups = [];
- }
- $value = json_encode($groups);
- $this->logger->info("Set groups: $value", ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_groups, $value);
- }
-
- /**
- * Get the list of groups
- *
- * @return array
- */
- public function GetLimitGroups() {
- $value = $this->config->getAppValue($this->appName, $this->_groups, "");
- if (empty($value)) {
- return [];
- }
- $groups = json_decode($value, true);
- if (!\is_array($groups)) {
- $groups = [];
- }
- return $groups;
- }
-
- /**
- * Check access for group
- *
- * @param string $userId - user identifier
- *
- * @return bool
- */
- public function isUserAllowedToUse($userId = null) {
- // no user -> no
- $userSession = \OC::$server->getUserSession();
- if ($userId === null && ($userSession === null || !$userSession->isLoggedIn())) {
- return false;
- }
-
- $groups = $this->GetLimitGroups();
- // no group set -> all users are allowed
- if (\count($groups) === 0) {
- return true;
- }
-
- if ($userId === null) {
- $user = $userSession->getUser();
- } else {
- $user = \OC::$server->getUserManager()->get($userId);
- if (empty($user)) {
- return false;
- }
- }
-
- foreach ($groups as $groupName) {
- // group unknown -> error and allow nobody
- $group = \OC::$server->getGroupManager()->get($groupName);
- if ($group === null) {
- \OC::$server->getLogger()->error("Group is unknown $groupName", ["app" => $this->appName]);
- $this->SetLimitGroups(array_diff($groups, [$groupName]));
- } else {
- if ($group->inGroup($user)) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Save the document service verification setting to the application configuration
- *
- * @param bool $verifyPeerOff - parameter verification setting
- */
- public function SetVerifyPeerOff($verifyPeerOff) {
- $this->logger->info("SetVerifyPeerOff " . json_encode($verifyPeerOff), ["app" => $this->appName]);
-
- $this->config->setAppValue($this->appName, $this->_verification, json_encode($verifyPeerOff));
- }
-
- /**
- * Get the document service verification setting to the application configuration
- *
- * @return bool
- */
- public function GetVerifyPeerOff() {
- $turnOff = $this->config->getAppValue($this->appName, $this->_verification, "");
-
- if (!empty($turnOff)) {
- return $turnOff === "true";
- }
-
- return $this->GetSystemValue($this->_verification);
- }
-
- /**
- * Get the limit on size document when generating thumbnails
- *
- * @return int
- */
- public function GetLimitThumbSize() {
- $limitSize = (integer)$this->GetSystemValue($this->_limitThumbSize);
-
- if (!empty($limitSize)) {
- return $limitSize;
- }
-
- return 100*1024*1024;
- }
-
- /**
- * Get the jwt header setting
- *
- * @param bool $origin - take origin
- *
- * @return string
- */
- public function JwtHeader($origin = false) {
- if (!$origin && $this->UseDemo()) {
- return $this->DEMO_PARAM["HEADER"];
- }
-
- $header = $this->config->getAppValue($this->appName, $this->_jwtHeader, "");
- if (empty($header)) {
- $header = $this->GetSystemValue($this->_jwtHeader);
- }
- if (!$origin && empty($header)) {
- $header = "Authorization";
- }
- return $header;
- }
-
- /**
- * Save the jwtHeader setting
- *
- * @param string $value - jwtHeader
- */
- public function SetJwtHeader($value) {
- $value = trim($value);
- if (empty($value)) {
- $this->logger->info("Clear header key", ["app" => $this->appName]);
- } else {
- $this->logger->info("Set header key " . $value, ["app" => $this->appName]);
- }
-
- $this->config->setAppValue($this->appName, $this->_jwtHeader, $value);
- }
-
- /**
- * Get the Jwt Leeway
- *
- * @return int
- */
- public function GetJwtLeeway() {
- $jwtLeeway = (integer)$this->GetSystemValue($this->_jwtLeeway);
-
- return $jwtLeeway;
- }
-
- /**
- * Save the status settings
- *
- * @param string $value - error
- */
- public function SetSettingsError($value) {
- $this->config->setAppValue($this->appName, $this->_settingsError, $value);
- }
-
- /**
- * Get the status settings
- *
- * @return bool
- */
- public function SettingsAreSuccessful() {
- return empty($this->config->getAppValue($this->appName, $this->_settingsError, ""));
- }
-
- /**
- * Checking encryption enabled
- *
- * @return string|bool
- */
- public function checkEncryptionModule() {
- if (!\OC::$server->getAppManager()->isInstalled("encryption")) {
- return false;
- }
- if (!\OC::$server->getEncryptionManager()->isEnabled()) {
- return false;
- }
-
- $crypt = new \OCA\Encryption\Crypto\Crypt(\OC::$server->getLogger(), \OC::$server->getUserSession(), \OC::$server->getConfig(), \OC::$server->getL10N("encryption"));
- $util = new \OCA\Encryption\Util(new \OC\Files\View(), $crypt, \OC::$server->getLogger(), \OC::$server->getUserSession(), \OC::$server->getConfig(), \OC::$server->getUserManager());
- if ($util->isMasterKeyEnabled()) {
- return "master";
- }
-
- return true;
- }
-
- /**
- * Get supported formats
- *
- * @return array
- *
- * @NoAdminRequired
- */
- public function FormatsSetting() {
- $result = $this->formats;
-
- $defFormats = $this->GetDefaultFormats();
- foreach ($defFormats as $format => $setting) {
- if (\array_key_exists($format, $result)) {
- $result[$format]["def"] = ($setting === true || $setting === "true");
- }
- }
-
- $editFormats = $this->GetEditableFormats();
- foreach ($editFormats as $format => $setting) {
- if (\array_key_exists($format, $result)) {
- $result[$format]["edit"] = ($setting === true || $setting === "true");
- }
- }
-
- return $result;
- }
-
- public function ShareAttributesVersion() {
- if (\version_compare(\implode(".", \OCP\Util::getVersion()), "10.3.0", ">=")) {
- return "v2";
- } elseif (\version_compare(\implode(".", \OCP\Util::getVersion()), "10.2.0", ">=")) {
- return "v1";
- }
- return "";
- }
-
- /**
- * Get the editors check interval
- *
- * @return int
- */
- public function GetEditorsCheckInterval() {
- $interval = $this->GetSystemValue($this->_editors_check_interval);
-
- if (empty($interval) && $interval !== 0) {
- $interval = 60*60*24;
- }
- return (integer)$interval;
- }
-
- /**
- * Additional data about formats
- *
- * @var array
- */
- private $formats = [
- "csv" => [ "mime" => "text/csv", "type" => "cell", "edit" => true, "editable" => true, "saveas" => ["ods", "pdf", "xlsx"] ],
- "doc" => [ "mime" => "application/msword", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
- "docm" => [ "mime" => "application/vnd.ms-word.document.macroEnabled.12", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
- "docx" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "type" => "word", "edit" => true, "def" => true, "review" => true, "comment" => true, "saveas" => ["odt", "pdf", "rtf", "txt"] ],
- "docxf" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf", "type" => "word", "edit" => true, "def" => true, "review" => true, "comment" => true, "saveas" => ["odt", "pdf", "rtf", "txt"], "createForm" => true ],
- "oform" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform", "type" => "word", "fillForms" => true, "def" => true ],
- "dot" => [ "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
- "dotx" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
- "epub" => [ "mime" => "application/epub+zip", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
- "htm" => [ "type" => "word", "conv" => true ],
- "html" => [ "mime" => "text/html", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
- "odp" => [ "mime" => "application/vnd.oasis.opendocument.presentation", "type" => "slide", "conv" => true, "editable" => true, "saveas" => ["pdf", "pptx"] ],
- "ods" => [ "mime" => "application/vnd.oasis.opendocument.spreadsheet", "type" => "cell", "conv" => true, "editable" => true, "saveas" => ["csv", "pdf", "xlsx"] ],
- "odt" => [ "mime" => "application/vnd.oasis.opendocument.text", "type" => "word", "conv" => true, "editable" => true, "saveas" => ["docx", "pdf", "rtf", "txt"] ],
- "otp" => [ "mime" => "application/vnd.oasis.opendocument.presentation-template", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
- "ots" => [ "mime" => "application/vnd.oasis.opendocument.spreadsheet-template", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ],
- "ott" => [ "mime" => "application/vnd.oasis.opendocument.text-template", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
- "pdf" => [ "mime" => "application/pdf", "type" => "word" ],
- "pot" => [ "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
- "potm" => [ "mime" => "application/vnd.ms-powerpoint.template.macroEnabled.12", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
- "potx" => [ "mime" => "application/vnd.openxmlformats-officedocument.presentationml.template", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
- "pps" => [ "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
- "ppsm" => [ "mime" => "application/vnd.ms-powerpoint.slideshow.macroEnabled.12", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
- "ppsx" => [ "mime" => "application/vnd.openxmlformats-officedocument.presentationml.slideshow", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
- "ppt" => [ "mime" => "application/vnd.ms-powerpoint", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
- "pptm" => [ "mime" => "application/vnd.ms-powerpoint.presentation.macroEnabled.12", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
- "pptx" => [ "mime" => "application/vnd.openxmlformats-officedocument.presentationml.presentation", "type" => "slide", "edit" => true, "def" => true, "comment" => true, "saveas" => ["pdf", "odp"] ],
- "rtf" => [ "mime" => "text/rtf", "type" => "word", "conv" => true, "editable" => true, "saveas" => ["docx", "odt", "pdf", "txt"] ],
- "txt" => [ "mime" => "text/plain", "type" => "word", "edit" => true, "editable" => true, "saveas" => ["docx", "odt", "pdf", "rtf"] ],
- "xls" => [ "mime" => "application/vnd.ms-excel", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ],
- "xlsm" => [ "mime" => "application/vnd.ms-excel.sheet.macroEnabled.12", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ],
- "xlsx" => [ "mime" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "type" => "cell", "edit" => true, "def" => true, "comment" => true, "modifyFilter" => true, "saveas" => ["csv", "ods", "pdf"] ],
- "xlt" => [ "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ],
- "xltm" => [ "mime" => "application/vnd.ms-excel.template.macroEnabled.12", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ],
- "xltx" => [ "mime" => "application/vnd.openxmlformats-officedocument.spreadsheetml.template", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ]
- ];
-
- /**
- * DEMO DATA
- */
- private $DEMO_PARAM = [
- "ADDR" => "https://onlinedocs.onlyoffice.com/",
- "HEADER" => "AuthorizationJWT",
- "SECRET" => "sn2puSUF7muF5Jas",
- "TRIAL" => 30
- ];
-
- private $linkToDocs = "https://www.onlyoffice.com/docs-registration.aspx?referer=owncloud";
-
- /**
- * Get link to Docs Cloud
- *
- * @return string
- */
- public function GetLinkToDocs() {
- return $this->linkToDocs;
- }
+ /**
+ * Application name
+ *
+ * @var string
+ */
+ private $appName;
+
+ /**
+ * Config service
+ *
+ * @var IConfig
+ */
+ private $config;
+
+ /**
+ * Logger
+ *
+ * @var ILogger
+ */
+ private $logger;
+
+ /**
+ * The config key for the demo server
+ *
+ * @var string
+ */
+ private $_demo = "demo";
+
+ /**
+ * The config key for the document server address
+ *
+ * @var string
+ */
+ private $_documentserver = "DocumentServerUrl";
+
+ /**
+ * The config key for the document server address available from ownCloud
+ *
+ * @var string
+ */
+ private $_documentserverInternal = "DocumentServerInternalUrl";
+
+ /**
+ * The config key for the ownCloud address available from document server
+ *
+ * @var string
+ */
+ private $_storageUrl = "StorageUrl";
+
+ /**
+ * The config key for the secret key
+ *
+ * @var string
+ */
+ private $_cryptSecret = "secret";
+
+ /**
+ * The config key for the default formats
+ *
+ * @var string
+ */
+ private $_defFormats = "defFormats";
+
+ /**
+ * The config key for the editable formats
+ *
+ * @var string
+ */
+ private $_editFormats = "editFormats";
+
+ /**
+ * The config key for the setting same tab
+ *
+ * @var string
+ */
+ private $_sameTab = "sameTab";
+
+ /**
+ * The config key for the generate preview
+ *
+ * @var string
+ */
+ private $_preview = "preview";
+
+ /**
+ * The config key for the keep versions history
+ *
+ * @var string
+ */
+ private $_versionHistory = "versionHistory";
+
+ /**
+ * The config key for the protection
+ *
+ * @var string
+ */
+ private $_protection = "protection";
+
+ /**
+ * The config key for the chat display setting
+ *
+ * @var string
+ */
+ private $_customizationChat = "customizationChat";
+
+ /**
+ * The config key for display the header more compact setting
+ *
+ * @var string
+ */
+ private $_customizationCompactHeader = "customizationCompactHeader";
+
+ /**
+ * The config key for the feedback display setting
+ *
+ * @var string
+ */
+ private $_customizationFeedback = "customizationFeedback";
+
+ /**
+ * The config key for the forcesave setting
+ *
+ * @var string
+ */
+ private $_customizationForcesave = "customizationForcesave";
+
+ /**
+ * The config key for the help display setting
+ *
+ * @var string
+ */
+ private $_customizationHelp = "customizationHelp";
+
+ /**
+ * The config key for the no tabs setting
+ *
+ * @var string
+ */
+ private $_customizationToolbarNoTabs = "customizationToolbarNoTabs";
+
+ /**
+ * The config key for the review mode setting
+ *
+ * @var string
+ */
+ private $_customizationReviewDisplay = "customizationReviewDisplay";
+
+ /**
+ * The config key for the theme setting
+ *
+ * @var string
+ */
+ private $_customizationTheme = "customizationTheme";
+
+ /**
+ * The config key for the setting limit groups
+ *
+ * @var string
+ */
+ private $_groups = "groups";
+
+ /**
+ * The config key for the verification
+ *
+ * @var string
+ */
+ private $_verification = "verify_peer_off";
+
+ /**
+ * The config key for the secret key in jwt
+ *
+ * @var string
+ */
+ private $_jwtSecret = "jwt_secret";
+
+ /**
+ * The config key for the jwt header
+ *
+ * @var string
+ */
+ private $_jwtHeader = "jwt_header";
+
+ /**
+ * The config key for the allowable leeway in Jwt checks
+ *
+ * @var string
+ */
+ private $_jwtLeeway = "jwt_leeway";
+
+ /**
+ * The config key for the settings error
+ *
+ * @var string
+ */
+ private $_settingsError = "settings_error";
+
+ /**
+ * The config key for limit thumbnail size
+ *
+ * @var string
+ */
+ public $_limitThumbSize = "limit_thumb_size";
+
+ /**
+ * The config key for the customer
+ *
+ * @var string
+ */
+ public $_customization_customer = "customization_customer";
+
+ /**
+ * The config key for the loaderLogo
+ *
+ * @var string
+ */
+ public $_customization_loaderLogo = "customization_loaderLogo";
+
+ /**
+ * The config key for the loaderName
+ *
+ * @var string
+ */
+ public $_customization_loaderName = "customization_loaderName";
+
+ /**
+ * The config key for the logo
+ *
+ * @var string
+ */
+ 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";
+
+ /**
+ * The config key for the goback
+ *
+ * @var string
+ */
+ public $_customization_goback = "customization_goback";
+
+ /**
+ * The config key for the macros
+ *
+ * @var string
+ */
+ public $_customization_macros = "customization_macros";
+
+ /**
+ * The config key for the plugins
+ *
+ * @var string
+ */
+ public $_customizationPlugins = "customization_plugins";
+
+ /**
+ * The config key for the interval of editors availability check by cron
+ *
+ * @var string
+ */
+ private $_editors_check_interval = "editors_check_interval";
+
+ /**
+ * @param string $AppName - application name
+ */
+ public function __construct($AppName) {
+ $this->appName = $AppName;
+
+ $this->config = \OC::$server->getConfig();
+ $this->logger = \OC::$server->getLogger();
+ }
+
+ /**
+ * Get value from the system configuration
+ *
+ * @param string $key - key configuration
+ * @param bool $system - get from root or from app section
+ *
+ * @return string
+ */
+ public function GetSystemValue($key, $system = false) {
+ if ($system) {
+ return $this->config->getSystemValue($key);
+ }
+ if (!empty($this->config->getSystemValue($this->appName))
+ && \array_key_exists($key, $this->config->getSystemValue($this->appName))) {
+ return $this->config->getSystemValue($this->appName)[$key];
+ }
+ return null;
+ }
+
+ /**
+ * Switch on demo server
+ *
+ * @param bool $value - select demo
+ *
+ * @return bool
+ */
+ public function SelectDemo($value) {
+ $this->logger->info("Select demo: " . json_encode($value), ["app" => $this->appName]);
+
+ $data = $this->GetDemoData();
+
+ if ($value === true && !$data["available"]) {
+ $this->logger->info("Trial demo is overdue: " . json_encode($data), ["app" => $this->appName]);
+ return false;
+ }
+
+ $data["enabled"] = $value === true;
+ if (!isset($data["start"])) {
+ $data["start"] = new DateTime();
+ }
+
+ $this->config->setAppValue($this->appName, $this->_demo, json_encode($data));
+ return true;
+ }
+
+ /**
+ * Get demo data
+ *
+ * @return array
+ */
+ public function GetDemoData() {
+ $data = $this->config->getAppValue($this->appName, $this->_demo, "");
+
+ if (empty($data)) {
+ return [
+ "available" => true,
+ "enabled" => false
+ ];
+ }
+ $data = json_decode($data, true);
+
+ $overdue = new DateTime(isset($data["start"]) ? $data["start"]["date"] : null);
+ $overdue->add(new DateInterval("P" . $this->DEMO_PARAM["TRIAL"] . "D"));
+ if ($overdue > new DateTime()) {
+ $data["available"] = true;
+ $data["enabled"] = $data["enabled"] === true;
+ } else {
+ $data["available"] = false;
+ $data["enabled"] = false;
+ }
+
+ return $data;
+ }
+
+ /**
+ * Get status of demo server
+ *
+ * @return bool
+ */
+ public function UseDemo() {
+ return $this->GetDemoData()["enabled"] === true;
+ }
+
+ /**
+ * Save the document service address to the application configuration
+ *
+ * @param string $documentServer - document service address
+ */
+ public function SetDocumentServerUrl($documentServer) {
+ $documentServer = trim($documentServer);
+ if (\strlen($documentServer) > 0) {
+ $documentServer = rtrim($documentServer, "/") . "/";
+ if (!preg_match("/(^https?:\/\/)|^\//i", $documentServer)) {
+ $documentServer = "http://" . $documentServer;
+ }
+ }
+
+ $this->logger->info("SetDocumentServerUrl: $documentServer", ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_documentserver, $documentServer);
+ }
+
+ /**
+ * Get the document service address from the application configuration
+ *
+ * @param bool $origin - take origin
+ *
+ * @return string
+ */
+ public function GetDocumentServerUrl($origin = false) {
+ if (!$origin && $this->UseDemo()) {
+ return $this->DEMO_PARAM["ADDR"];
+ }
+
+ $url = $this->config->getAppValue($this->appName, $this->_documentserver, "");
+ if (empty($url)) {
+ $url = $this->GetSystemValue($this->_documentserver);
+ }
+ if ($url !== "/") {
+ $url = rtrim($url, "/");
+ if (\strlen($url) > 0) {
+ $url = $url . "/";
+ }
+ }
+ return $url;
+ }
+
+ /**
+ * Save the document service address available from ownCloud to the application configuration
+ *
+ * @param string $documentServerInternal - document service address
+ */
+ public function SetDocumentServerInternalUrl($documentServerInternal) {
+ $documentServerInternal = rtrim(trim($documentServerInternal), "/");
+ if (\strlen($documentServerInternal) > 0) {
+ $documentServerInternal = $documentServerInternal . "/";
+ if (!preg_match("/^https?:\/\//i", $documentServerInternal)) {
+ $documentServerInternal = "http://" . $documentServerInternal;
+ }
+ }
+
+ $this->logger->info("SetDocumentServerInternalUrl: $documentServerInternal", ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_documentserverInternal, $documentServerInternal);
+ }
+
+ /**
+ * Get the document service address available from ownCloud from the application configuration
+ *
+ * @param bool $origin - take origin
+ *
+ * @return string
+ */
+ public function GetDocumentServerInternalUrl($origin = false) {
+ if (!$origin && $this->UseDemo()) {
+ return $this->GetDocumentServerUrl();
+ }
+
+ $url = $this->config->getAppValue($this->appName, $this->_documentserverInternal, "");
+ if (empty($url)) {
+ $url = $this->GetSystemValue($this->_documentserverInternal);
+ }
+ if (!$origin && empty($url)) {
+ $url = $this->GetDocumentServerUrl();
+ }
+ return $url;
+ }
+
+ /**
+ * Replace domain in document server url with internal address from configuration
+ *
+ * @param string $url - document server url
+ *
+ * @return string
+ */
+ public function ReplaceDocumentServerUrlToInternal($url) {
+ $documentServerUrl = $this->GetDocumentServerInternalUrl();
+ if (!empty($documentServerUrl)) {
+ $from = $this->GetDocumentServerUrl();
+
+ if (!preg_match("/^https?:\/\//i", $from)) {
+ $parsedUrl = parse_url($url);
+ $from = $parsedUrl["scheme"] . "://" . $parsedUrl["host"] . (\array_key_exists("port", $parsedUrl) ? (":" . $parsedUrl["port"]) : "") . $from;
+ }
+
+ if ($from !== $documentServerUrl) {
+ $this->logger->debug("Replace url from $from to $documentServerUrl", ["app" => $this->appName]);
+ $url = str_replace($from, $documentServerUrl, $url);
+ }
+ }
+
+ return $url;
+ }
+
+ /**
+ * Save the ownCloud address available from document server to the application configuration
+ *
+ * @param string $documentServer - document service address
+ */
+ public function SetStorageUrl($storageUrl) {
+ $storageUrl = rtrim(trim($storageUrl), "/");
+ if (\strlen($storageUrl) > 0) {
+ $storageUrl = $storageUrl . "/";
+ if (!preg_match("/^https?:\/\//i", $storageUrl)) {
+ $storageUrl = "http://" . $storageUrl;
+ }
+ }
+
+ $this->logger->info("SetStorageUrl: $storageUrl", ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_storageUrl, $storageUrl);
+ }
+
+ /**
+ * Get the ownCloud address available from document server from the application configuration
+ *
+ * @return string
+ */
+ public function GetStorageUrl() {
+ $url = $this->config->getAppValue($this->appName, $this->_storageUrl, "");
+ if (empty($url)) {
+ $url = $this->GetSystemValue($this->_storageUrl);
+ }
+ return $url;
+ }
+
+ /**
+ * Save the document service secret key to the application configuration
+ *
+ * @param string $secret - secret key
+ */
+ public function SetDocumentServerSecret($secret) {
+ $secret = trim($secret);
+ if (empty($secret)) {
+ $this->logger->info("Clear secret key", ["app" => $this->appName]);
+ } else {
+ $this->logger->info("Set secret key", ["app" => $this->appName]);
+ }
+
+ $this->config->setAppValue($this->appName, $this->_jwtSecret, $secret);
+ }
+
+ /**
+ * Get the document service secret key from the application configuration
+ *
+ * @param bool $origin - take origin
+ *
+ * @return string
+ */
+ public function GetDocumentServerSecret($origin = false) {
+ if (!$origin && $this->UseDemo()) {
+ return $this->DEMO_PARAM["SECRET"];
+ }
+
+ $secret = $this->config->getAppValue($this->appName, $this->_jwtSecret, "");
+ if (empty($secret)) {
+ $secret = $this->GetSystemValue($this->_jwtSecret);
+ }
+ return $secret;
+ }
+
+ /**
+ * Get the secret key from the application configuration
+ *
+ * @return string
+ */
+ public function GetSKey() {
+ $secret = $this->GetDocumentServerSecret();
+ if (empty($secret)) {
+ $secret = $this->GetSystemValue($this->_cryptSecret, true);
+ }
+ return $secret;
+ }
+
+ /**
+ * Save an array of formats with default action
+ *
+ * @param array $formats - formats with status
+ */
+ public function SetDefaultFormats($formats) {
+ $value = json_encode($formats);
+ $this->logger->info("Set default formats: $value", ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_defFormats, $value);
+ }
+
+ /**
+ * Get an array of formats with default action
+ *
+ * @return array
+ */
+ private function GetDefaultFormats() {
+ $value = $this->config->getAppValue($this->appName, $this->_defFormats, "");
+ if (empty($value)) {
+ return [];
+ }
+ return json_decode($value, true);
+ }
+
+ /**
+ * Save an array of formats that is opened for editing
+ *
+ * @param array $formats - formats with status
+ */
+ public function SetEditableFormats($formats) {
+ $value = json_encode($formats);
+ $this->logger->info("Set editing formats: $value", ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_editFormats, $value);
+ }
+
+ /**
+ * Get an array of formats opening for editing
+ *
+ * @return array
+ */
+ private function GetEditableFormats() {
+ $value = $this->config->getAppValue($this->appName, $this->_editFormats, "");
+ if (empty($value)) {
+ return [];
+ }
+ return json_decode($value, true);
+ }
+
+ /**
+ * Save the opening setting in a same tab
+ *
+ * @param bool $value - same tab
+ */
+ public function SetSameTab($value) {
+ $this->logger->info("Set opening in a same tab: " . json_encode($value), ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_sameTab, json_encode($value));
+ }
+
+ /**
+ * Get the opening setting in a same tab
+ *
+ * @return bool
+ */
+ public function GetSameTab() {
+ return $this->config->getAppValue($this->appName, $this->_sameTab, "false") === "true";
+ }
+
+ /**
+ * Save generate preview setting
+ *
+ * @param bool $value - preview
+ */
+ public function SetPreview($value) {
+ $this->logger->info("Set generate preview: " . json_encode($value), ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_preview, json_encode($value));
+ }
+
+ /**
+ * Get generate preview setting
+ *
+ * @return bool
+ */
+ public function GetPreview() {
+ return $this->config->getAppValue($this->appName, $this->_preview, "true") === "true";
+ }
+
+ /**
+ * Save keep versions history
+ *
+ * @param bool $value - version history
+ */
+ public function SetVersionHistory($value) {
+ $this->logger->info("Set keep versions history: " . json_encode($value), ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_versionHistory, json_encode($value));
+ }
+
+ /**
+ * Get keep versions history
+ *
+ * @return bool
+ */
+ public function GetVersionHistory() {
+ return $this->config->getAppValue($this->appName, $this->_versionHistory, "true") === "true";
+ }
+
+ /**
+ * Save protection
+ *
+ * @param bool $value - version history
+ */
+ public function SetProtection($value) {
+ $this->logger->info("Set protection: " . $value, ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_protection, $value);
+ }
+
+ /**
+ * Get protection
+ *
+ * @return bool
+ */
+ public function GetProtection() {
+ $value = $this->config->getAppValue($this->appName, $this->_protection, "owner");
+ if ($value === "all") {
+ return "all";
+ }
+ return "owner";
+ }
+
+ /**
+ * Save chat display setting
+ *
+ * @param bool $value - display chat
+ */
+ public function SetCustomizationChat($value) {
+ $this->logger->info("Set chat display: " . json_encode($value), ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_customizationChat, json_encode($value));
+ }
+
+ /**
+ * Get chat display setting
+ *
+ * @return bool
+ */
+ public function GetCustomizationChat() {
+ return $this->config->getAppValue($this->appName, $this->_customizationChat, "true") === "true";
+ }
+
+ /**
+ * Save compact header setting
+ *
+ * @param bool $value - display compact header
+ */
+ public function SetCustomizationCompactHeader($value) {
+ $this->logger->info("Set compact header display: " . json_encode($value), ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_customizationCompactHeader, json_encode($value));
+ }
+
+ /**
+ * Get compact header setting
+ *
+ * @return bool
+ */
+ public function GetCustomizationCompactHeader() {
+ return $this->config->getAppValue($this->appName, $this->_customizationCompactHeader, "true") === "true";
+ }
+
+ /**
+ * Save feedback display setting
+ *
+ * @param bool $value - display feedback
+ */
+ public function SetCustomizationFeedback($value) {
+ $this->logger->info("Set feedback display: " . json_encode($value), ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_customizationFeedback, json_encode($value));
+ }
+
+ /**
+ * Get feedback display setting
+ *
+ * @return bool
+ */
+ public function GetCustomizationFeedback() {
+ return $this->config->getAppValue($this->appName, $this->_customizationFeedback, "true") === "true";
+ }
+
+ /**
+ * Save forcesave setting
+ *
+ * @param bool $value - forcesave
+ */
+ public function SetCustomizationForcesave($value) {
+ $this->logger->info("Set forcesave: " . json_encode($value), ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_customizationForcesave, json_encode($value));
+ }
+
+ /**
+ * Get forcesave setting
+ *
+ * @return bool
+ */
+ public function GetCustomizationForcesave() {
+ $value = $this->config->getAppValue($this->appName, $this->_customizationForcesave, "false") === "true";
+
+ return $value && ($this->checkEncryptionModule() === false);
+ }
+
+ /**
+ * Save help display setting
+ *
+ * @param bool $value - display help
+ */
+ public function SetCustomizationHelp($value) {
+ $this->logger->info("Set help display: " . json_encode($value), ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_customizationHelp, json_encode($value));
+ }
+
+ /**
+ * Get help display setting
+ *
+ * @return bool
+ */
+ public function GetCustomizationHelp() {
+ return $this->config->getAppValue($this->appName, $this->_customizationHelp, "true") === "true";
+ }
+
+ /**
+ * Save without tabs setting
+ *
+ * @param bool $value - without tabs
+ */
+ public function SetCustomizationToolbarNoTabs($value) {
+ $this->logger->info("Set without tabs: " . json_encode($value), ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_customizationToolbarNoTabs, json_encode($value));
+ }
+
+ /**
+ * Get without tabs setting
+ *
+ * @return bool
+ */
+ public function GetCustomizationToolbarNoTabs() {
+ return $this->config->getAppValue($this->appName, $this->_customizationToolbarNoTabs, "true") === "true";
+ }
+
+ /**
+ * Save review viewing mode setting
+ *
+ * @param string $value - review mode
+ */
+ public function SetCustomizationReviewDisplay($value) {
+ $this->logger->info("Set review mode: " . $value, ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_customizationReviewDisplay, $value);
+ }
+
+ /**
+ * Get review viewing mode setting
+ *
+ * @return string
+ */
+ public function GetCustomizationReviewDisplay() {
+ $value = $this->config->getAppValue($this->appName, $this->_customizationReviewDisplay, "original");
+ if ($value === "markup") {
+ return "markup";
+ }
+ if ($value === "final") {
+ return "final";
+ }
+ return "original";
+ }
+
+ /**
+ * Save theme setting
+ *
+ * @param string $value - theme
+ */
+ public function SetCustomizationTheme($value) {
+ $this->logger->info("Set theme: " . $value, ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_customizationTheme, $value);
+ }
+
+ /**
+ * Get theme setting
+ *
+ * @return string
+ */
+ public function GetCustomizationTheme() {
+ $value = $this->config->getAppValue($this->appName, $this->_customizationTheme, "theme-classic-light");
+ if ($value === "theme-light") {
+ return "theme-light";
+ }
+ if ($value === "theme-dark") {
+ return "theme-dark";
+ }
+ return "theme-classic-light";
+ }
+
+ /**
+ * Save macros setting
+ *
+ * @param bool $value - enable macros
+ */
+ public function SetCustomizationMacros($value) {
+ $this->logger->info("Set macros enabled: " . json_encode($value), ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_customization_macros, json_encode($value));
+ }
+
+ /**
+ * Get macros setting
+ *
+ * @return bool
+ */
+ public function GetCustomizationMacros() {
+ return $this->config->getAppValue($this->appName, $this->_customization_macros, "true") === "true";
+ }
+
+ /**
+ * Save plugins setting
+ *
+ * @param bool $value - enable macros
+ */
+ public function SetCustomizationPlugins($value) {
+ $this->logger->info("Set plugins enabled: " . json_encode($value), ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_customizationPlugins, json_encode($value));
+ }
+
+ /**
+ * Get plugins setting
+ *
+ * @return bool
+ */
+ public function GetCustomizationPlugins() {
+ return $this->config->getAppValue($this->appName, $this->_customizationPlugins, "true") === "true";
+ }
+
+ /**
+ * Save the list of groups
+ *
+ * @param array $groups - the list of groups
+ */
+ public function SetLimitGroups($groups) {
+ if (!\is_array($groups)) {
+ $groups = [];
+ }
+ $value = json_encode($groups);
+ $this->logger->info("Set groups: $value", ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_groups, $value);
+ }
+
+ /**
+ * Get the list of groups
+ *
+ * @return array
+ */
+ public function GetLimitGroups() {
+ $value = $this->config->getAppValue($this->appName, $this->_groups, "");
+ if (empty($value)) {
+ return [];
+ }
+ $groups = json_decode($value, true);
+ if (!\is_array($groups)) {
+ $groups = [];
+ }
+ return $groups;
+ }
+
+ /**
+ * Check access for group
+ *
+ * @param string $userId - user identifier
+ *
+ * @return bool
+ */
+ public function isUserAllowedToUse($userId = null) {
+ // no user -> no
+ $userSession = \OC::$server->getUserSession();
+ if ($userId === null && ($userSession === null || !$userSession->isLoggedIn())) {
+ return false;
+ }
+
+ $groups = $this->GetLimitGroups();
+ // no group set -> all users are allowed
+ if (\count($groups) === 0) {
+ return true;
+ }
+
+ if ($userId === null) {
+ $user = $userSession->getUser();
+ } else {
+ $user = \OC::$server->getUserManager()->get($userId);
+ if (empty($user)) {
+ return false;
+ }
+ }
+
+ foreach ($groups as $groupName) {
+ // group unknown -> error and allow nobody
+ $group = \OC::$server->getGroupManager()->get($groupName);
+ if ($group === null) {
+ \OC::$server->getLogger()->error("Group is unknown $groupName", ["app" => $this->appName]);
+ $this->SetLimitGroups(array_diff($groups, [$groupName]));
+ } else {
+ if ($group->inGroup($user)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Save the document service verification setting to the application configuration
+ *
+ * @param bool $verifyPeerOff - parameter verification setting
+ */
+ public function SetVerifyPeerOff($verifyPeerOff) {
+ $this->logger->info("SetVerifyPeerOff " . json_encode($verifyPeerOff), ["app" => $this->appName]);
+
+ $this->config->setAppValue($this->appName, $this->_verification, json_encode($verifyPeerOff));
+ }
+
+ /**
+ * Get the document service verification setting to the application configuration
+ *
+ * @return bool
+ */
+ public function GetVerifyPeerOff() {
+ $turnOff = $this->config->getAppValue($this->appName, $this->_verification, "");
+
+ if (!empty($turnOff)) {
+ return $turnOff === "true";
+ }
+
+ return $this->GetSystemValue($this->_verification);
+ }
+
+ /**
+ * Get the limit on size document when generating thumbnails
+ *
+ * @return int
+ */
+ public function GetLimitThumbSize() {
+ $limitSize = (integer)$this->GetSystemValue($this->_limitThumbSize);
+
+ if (!empty($limitSize)) {
+ return $limitSize;
+ }
+
+ return 100*1024*1024;
+ }
+
+ /**
+ * Get the jwt header setting
+ *
+ * @param bool $origin - take origin
+ *
+ * @return string
+ */
+ public function JwtHeader($origin = false) {
+ if (!$origin && $this->UseDemo()) {
+ return $this->DEMO_PARAM["HEADER"];
+ }
+
+ $header = $this->config->getAppValue($this->appName, $this->_jwtHeader, "");
+ if (empty($header)) {
+ $header = $this->GetSystemValue($this->_jwtHeader);
+ }
+ if (!$origin && empty($header)) {
+ $header = "Authorization";
+ }
+ return $header;
+ }
+
+ /**
+ * Save the jwtHeader setting
+ *
+ * @param string $value - jwtHeader
+ */
+ public function SetJwtHeader($value) {
+ $value = trim($value);
+ if (empty($value)) {
+ $this->logger->info("Clear header key", ["app" => $this->appName]);
+ } else {
+ $this->logger->info("Set header key " . $value, ["app" => $this->appName]);
+ }
+
+ $this->config->setAppValue($this->appName, $this->_jwtHeader, $value);
+ }
+
+ /**
+ * Get the Jwt Leeway
+ *
+ * @return int
+ */
+ public function GetJwtLeeway() {
+ $jwtLeeway = (integer)$this->GetSystemValue($this->_jwtLeeway);
+
+ return $jwtLeeway;
+ }
+
+ /**
+ * Save the status settings
+ *
+ * @param string $value - error
+ */
+ public function SetSettingsError($value) {
+ $this->config->setAppValue($this->appName, $this->_settingsError, $value);
+ }
+
+ /**
+ * Get the status settings
+ *
+ * @return bool
+ */
+ public function SettingsAreSuccessful() {
+ return empty($this->config->getAppValue($this->appName, $this->_settingsError, ""));
+ }
+
+ /**
+ * Checking encryption enabled
+ *
+ * @return string|bool
+ */
+ public function checkEncryptionModule() {
+ if (!\OC::$server->getAppManager()->isInstalled("encryption")) {
+ return false;
+ }
+ if (!\OC::$server->getEncryptionManager()->isEnabled()) {
+ return false;
+ }
+
+ $crypt = new \OCA\Encryption\Crypto\Crypt(\OC::$server->getLogger(), \OC::$server->getUserSession(), \OC::$server->getConfig(), \OC::$server->getL10N("encryption"));
+ $util = new \OCA\Encryption\Util(new \OC\Files\View(), $crypt, \OC::$server->getLogger(), \OC::$server->getUserSession(), \OC::$server->getConfig(), \OC::$server->getUserManager());
+ if ($util->isMasterKeyEnabled()) {
+ return "master";
+ }
+
+ return true;
+ }
+
+ /**
+ * Get supported formats
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ */
+ public function FormatsSetting() {
+ $result = $this->formats;
+
+ $defFormats = $this->GetDefaultFormats();
+ foreach ($defFormats as $format => $setting) {
+ if (\array_key_exists($format, $result)) {
+ $result[$format]["def"] = ($setting === true || $setting === "true");
+ }
+ }
+
+ $editFormats = $this->GetEditableFormats();
+ foreach ($editFormats as $format => $setting) {
+ if (\array_key_exists($format, $result)) {
+ $result[$format]["edit"] = ($setting === true || $setting === "true");
+ }
+ }
+
+ return $result;
+ }
+
+ public function ShareAttributesVersion() {
+ if (\version_compare(\implode(".", \OCP\Util::getVersion()), "10.3.0", ">=")) {
+ return "v2";
+ } elseif (\version_compare(\implode(".", \OCP\Util::getVersion()), "10.2.0", ">=")) {
+ return "v1";
+ }
+ return "";
+ }
+
+ /**
+ * Get the editors check interval
+ *
+ * @return int
+ */
+ public function GetEditorsCheckInterval() {
+ $interval = $this->GetSystemValue($this->_editors_check_interval);
+
+ if (empty($interval) && $interval !== 0) {
+ $interval = 60*60*24;
+ }
+ return (integer)$interval;
+ }
+
+ /**
+ * Additional data about formats
+ *
+ * @var array
+ */
+ private $formats = [
+ "csv" => [ "mime" => "text/csv", "type" => "cell", "edit" => true, "editable" => true, "saveas" => ["ods", "pdf", "xlsx"] ],
+ "doc" => [ "mime" => "application/msword", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
+ "docm" => [ "mime" => "application/vnd.ms-word.document.macroEnabled.12", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
+ "docx" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "type" => "word", "edit" => true, "def" => true, "review" => true, "comment" => true, "saveas" => ["odt", "pdf", "rtf", "txt"] ],
+ "docxf" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf", "type" => "word", "edit" => true, "def" => true, "review" => true, "comment" => true, "saveas" => ["odt", "pdf", "rtf", "txt"], "createForm" => true ],
+ "oform" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform", "type" => "word", "fillForms" => true, "def" => true ],
+ "dot" => [ "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
+ "dotx" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
+ "epub" => [ "mime" => "application/epub+zip", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
+ "htm" => [ "type" => "word", "conv" => true ],
+ "html" => [ "mime" => "text/html", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
+ "odp" => [ "mime" => "application/vnd.oasis.opendocument.presentation", "type" => "slide", "conv" => true, "editable" => true, "saveas" => ["pdf", "pptx"] ],
+ "ods" => [ "mime" => "application/vnd.oasis.opendocument.spreadsheet", "type" => "cell", "conv" => true, "editable" => true, "saveas" => ["csv", "pdf", "xlsx"] ],
+ "odt" => [ "mime" => "application/vnd.oasis.opendocument.text", "type" => "word", "conv" => true, "editable" => true, "saveas" => ["docx", "pdf", "rtf", "txt"] ],
+ "otp" => [ "mime" => "application/vnd.oasis.opendocument.presentation-template", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
+ "ots" => [ "mime" => "application/vnd.oasis.opendocument.spreadsheet-template", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ],
+ "ott" => [ "mime" => "application/vnd.oasis.opendocument.text-template", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ],
+ "pdf" => [ "mime" => "application/pdf", "type" => "word" ],
+ "pot" => [ "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
+ "potm" => [ "mime" => "application/vnd.ms-powerpoint.template.macroEnabled.12", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
+ "potx" => [ "mime" => "application/vnd.openxmlformats-officedocument.presentationml.template", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
+ "pps" => [ "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
+ "ppsm" => [ "mime" => "application/vnd.ms-powerpoint.slideshow.macroEnabled.12", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
+ "ppsx" => [ "mime" => "application/vnd.openxmlformats-officedocument.presentationml.slideshow", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
+ "ppt" => [ "mime" => "application/vnd.ms-powerpoint", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
+ "pptm" => [ "mime" => "application/vnd.ms-powerpoint.presentation.macroEnabled.12", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ],
+ "pptx" => [ "mime" => "application/vnd.openxmlformats-officedocument.presentationml.presentation", "type" => "slide", "edit" => true, "def" => true, "comment" => true, "saveas" => ["pdf", "odp"] ],
+ "rtf" => [ "mime" => "text/rtf", "type" => "word", "conv" => true, "editable" => true, "saveas" => ["docx", "odt", "pdf", "txt"] ],
+ "txt" => [ "mime" => "text/plain", "type" => "word", "edit" => true, "editable" => true, "saveas" => ["docx", "odt", "pdf", "rtf"] ],
+ "xls" => [ "mime" => "application/vnd.ms-excel", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ],
+ "xlsm" => [ "mime" => "application/vnd.ms-excel.sheet.macroEnabled.12", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ],
+ "xlsx" => [ "mime" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "type" => "cell", "edit" => true, "def" => true, "comment" => true, "modifyFilter" => true, "saveas" => ["csv", "ods", "pdf"] ],
+ "xlt" => [ "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ],
+ "xltm" => [ "mime" => "application/vnd.ms-excel.template.macroEnabled.12", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ],
+ "xltx" => [ "mime" => "application/vnd.openxmlformats-officedocument.spreadsheetml.template", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ]
+ ];
+
+ /**
+ * DEMO DATA
+ */
+ private $DEMO_PARAM = [
+ "ADDR" => "https://onlinedocs.onlyoffice.com/",
+ "HEADER" => "AuthorizationJWT",
+ "SECRET" => "sn2puSUF7muF5Jas",
+ "TRIAL" => 30
+ ];
+
+ private $linkToDocs = "https://www.onlyoffice.com/docs-registration.aspx?referer=owncloud";
+
+ /**
+ * Get link to Docs Cloud
+ *
+ * @return string
+ */
+ public function GetLinkToDocs() {
+ return $this->linkToDocs;
+ }
}
diff --git a/lib/command/documentserver.php b/lib/command/documentserver.php
index 33c589f2..adda3514 100644
--- a/lib/command/documentserver.php
+++ b/lib/command/documentserver.php
@@ -32,101 +32,101 @@
use OCA\Onlyoffice\Crypt;
class DocumentServer extends Command {
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- private $config;
-
- /**
- * l10n service
- *
- * @var IL10N
- */
- private $trans;
-
- /**
- * Url generator service
- *
- * @var IURLGenerator
- */
- private $urlGenerator;
-
- /**
- * Hash generator
- *
- * @var Crypt
- */
- private $crypt;
-
- /**
- * @param AppConfig $config - application configuration
- * @param IL10N $trans - l10n service
- * @param IURLGenerator $urlGenerator - url generator service
- * @param Crypt $crypt - hash generator
- */
- public function __construct(
- AppConfig $config,
- IL10N $trans,
- IURLGenerator $urlGenerator,
- Crypt $crypt
- ) {
- parent::__construct();
- $this->config = $config;
- $this->trans = $trans;
- $this->urlGenerator = $urlGenerator;
- $this->crypt = $crypt;
- }
-
- /**
- * Configures the current command.
- */
- protected function configure() {
- $this
- ->setName("onlyoffice:documentserver")
- ->setDescription("Manage document server")
- ->addOption(
- "check",
- null,
- InputOption::VALUE_NONE,
- "Check connection document server"
- );
- }
-
- /**
- * Executes the current command.
- *
- * @param InputInterface $input - input data
- * @param OutputInterface $output - output data
- *
- * @return int 0 if everything went fine, or an exit code
- */
- protected function execute(InputInterface $input, OutputInterface $output) {
- $check = $input->getOption("check");
-
- $documentserver = $this->config->GetDocumentServerUrl(true);
- if (empty($documentserver)) {
- $output->writeln("Document server is not configured");
- return 1;
- }
-
- if ($check) {
- $documentService = new DocumentService($this->trans, $this->config);
-
- list($error, $version) = $documentService->checkDocServiceUrl($this->urlGenerator, $this->crypt);
- $this->config->SetSettingsError($error);
-
- if (!empty($error)) {
- $output->writeln("Error connection: $error");
- return 1;
- } else {
- $output->writeln("Document server $documentserver version $version is successfully connected");
- return 0;
- }
- }
-
- $output->writeln("The current document server: $documentserver");
- return 0;
- }
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ private $config;
+
+ /**
+ * l10n service
+ *
+ * @var IL10N
+ */
+ private $trans;
+
+ /**
+ * Url generator service
+ *
+ * @var IURLGenerator
+ */
+ private $urlGenerator;
+
+ /**
+ * Hash generator
+ *
+ * @var Crypt
+ */
+ private $crypt;
+
+ /**
+ * @param AppConfig $config - application configuration
+ * @param IL10N $trans - l10n service
+ * @param IURLGenerator $urlGenerator - url generator service
+ * @param Crypt $crypt - hash generator
+ */
+ public function __construct(
+ AppConfig $config,
+ IL10N $trans,
+ IURLGenerator $urlGenerator,
+ Crypt $crypt
+ ) {
+ parent::__construct();
+ $this->config = $config;
+ $this->trans = $trans;
+ $this->urlGenerator = $urlGenerator;
+ $this->crypt = $crypt;
+ }
+
+ /**
+ * Configures the current command.
+ */
+ protected function configure() {
+ $this
+ ->setName("onlyoffice:documentserver")
+ ->setDescription("Manage document server")
+ ->addOption(
+ "check",
+ null,
+ InputOption::VALUE_NONE,
+ "Check connection document server"
+ );
+ }
+
+ /**
+ * Executes the current command.
+ *
+ * @param InputInterface $input - input data
+ * @param OutputInterface $output - output data
+ *
+ * @return int 0 if everything went fine, or an exit code
+ */
+ protected function execute(InputInterface $input, OutputInterface $output) {
+ $check = $input->getOption("check");
+
+ $documentserver = $this->config->GetDocumentServerUrl(true);
+ if (empty($documentserver)) {
+ $output->writeln("Document server is not configured");
+ return 1;
+ }
+
+ if ($check) {
+ $documentService = new DocumentService($this->trans, $this->config);
+
+ list($error, $version) = $documentService->checkDocServiceUrl($this->urlGenerator, $this->crypt);
+ $this->config->SetSettingsError($error);
+
+ if (!empty($error)) {
+ $output->writeln("Error connection: $error");
+ return 1;
+ } else {
+ $output->writeln("Document server $documentserver version $version is successfully connected");
+ return 0;
+ }
+ }
+
+ $output->writeln("The current document server: $documentserver");
+ return 0;
+ }
}
diff --git a/lib/cron/editorscheck.php b/lib/cron/editorscheck.php
index 69065c4f..e9aa5054 100644
--- a/lib/cron/editorscheck.php
+++ b/lib/cron/editorscheck.php
@@ -37,156 +37,156 @@
*
*/
class EditorsCheck extends TimedJob {
- /**
- * Application name
- *
- * @var string
- */
- private $appName;
-
- /**
- * Url generator service
- *
- * @var IURLGenerator
- */
- private $urlGenerator;
-
- /**
- * Logger
- *
- * @var OCP\ILogger
- */
- private $logger;
-
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- private $config;
-
- /**
- * l10n service
- *
- * @var IL10N
- */
- private $trans;
-
- /**
- * Hash generator
- *
- * @var Crypt
- */
- private $crypt;
-
- /**
- * Group manager
- *
- * @var IGroupManager
- */
- private $groupManager;
-
- /**
- * @param string $AppName - application name
- * @param IURLGenerator $urlGenerator - url generator service
- * @param ITimeFactory $time - time
- * @param AppConfig $config - application configuration
- * @param IL10N $trans - l10n service
- * @param Crypt $crypt - crypt service
- */
- public function __construct(
- string $AppName,
- IURLGenerator $urlGenerator,
- ITimeFactory $time,
- AppConfig $config,
- IL10N $trans,
- Crypt $crypt,
- IGroupManager $groupManager
- ) {
- $this->appName = $AppName;
- $this->urlGenerator = $urlGenerator;
-
- $this->logger = \OC::$server->getLogger();
- $this->config = $config;
- $this->trans = $trans;
- $this->crypt = $crypt;
- $this->groupManager = $groupManager;
- $this->setInterval($this->config->GetEditorsCheckInterval());
- }
-
- /**
- * Makes the background check
- *
- * @param array $argument unused argument
- */
- protected function run($argument) {
- if (empty($this->config->GetDocumentServerUrl())) {
- $this->logger->debug("Settings are empty", ["app" => $this->appName]);
- return;
- }
- if (!$this->config->SettingsAreSuccessful()) {
- $this->logger->debug("Settings are not correct", ["app" => $this->appName]);
- return;
- }
- $fileUrl = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.emptyfile");
- if (!$this->config->UseDemo() && !empty($this->config->GetStorageUrl())) {
- $fileUrl = str_replace($this->urlGenerator->getAbsoluteURL("/"), $this->config->GetStorageUrl(), $fileUrl);
- }
- $host = parse_url($fileUrl)["host"];
- if ($host === "localhost" || $host === "127.0.0.1") {
- $this->logger->debug("Localhost is not alowed for cron editors availability check. Please provide server address for internal requests from ONLYOFFICE Docs", ["app" => $this->appName]);
- return;
- }
-
- $this->logger->debug("ONLYOFFICE check started by cron", ["app" => $this->appName]);
-
- $documentService = new DocumentService($this->trans, $this->config);
- list($error, $version) = $documentService->checkDocServiceUrl($this->urlGenerator, $this->crypt);
- if (!empty($error)) {
- $this->logger->info("ONLYOFFICE server is not available", ["app" => $this->appName]);
- $this->config->SetSettingsError($error);
- $this->notifyAdmins();
- } else {
- $this->logger->debug("ONLYOFFICE server availability check is finished successfully", ["app" => $this->appName]);
- }
- }
-
- /**
- * Get the list of users to notify
- *
- * @return string[]
- */
- private function getUsersToNotify() {
- $notifyGroups = ["admin"];
- $notifyUsers = [];
-
- foreach ($notifyGroups as $notifyGroup) {
- $group = $this->groupManager->get($notifyGroup);
- if ($group === null || !($group instanceof IGroup)) {
- continue;
- }
- $users = $group->getUsers();
- foreach ($users as $user) {
- $notifyUsers[] = $user->getUID();
- }
- }
- return $notifyUsers;
- }
-
- /**
- * Send notification to admins
- * @return void
- */
- private function notifyAdmins() {
- $notificationManager = \OC::$server->getNotificationManager();
- $notification = $notificationManager->createNotification();
- $notification->setApp($this->appName)
- ->setDateTime(new \DateTime())
- ->setObject("editorsCheck", $this->trans->t("ONLYOFFICE server is not available"))
- ->setSubject("editorscheck_info");
- foreach ($this->getUsersToNotify() as $uid) {
- $notification->setUser($uid);
- $notificationManager->notify($notification);
- }
- }
+ /**
+ * Application name
+ *
+ * @var string
+ */
+ private $appName;
+
+ /**
+ * Url generator service
+ *
+ * @var IURLGenerator
+ */
+ private $urlGenerator;
+
+ /**
+ * Logger
+ *
+ * @var OCP\ILogger
+ */
+ private $logger;
+
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ private $config;
+
+ /**
+ * l10n service
+ *
+ * @var IL10N
+ */
+ private $trans;
+
+ /**
+ * Hash generator
+ *
+ * @var Crypt
+ */
+ private $crypt;
+
+ /**
+ * Group manager
+ *
+ * @var IGroupManager
+ */
+ private $groupManager;
+
+ /**
+ * @param string $AppName - application name
+ * @param IURLGenerator $urlGenerator - url generator service
+ * @param ITimeFactory $time - time
+ * @param AppConfig $config - application configuration
+ * @param IL10N $trans - l10n service
+ * @param Crypt $crypt - crypt service
+ */
+ public function __construct(
+ string $AppName,
+ IURLGenerator $urlGenerator,
+ ITimeFactory $time,
+ AppConfig $config,
+ IL10N $trans,
+ Crypt $crypt,
+ IGroupManager $groupManager
+ ) {
+ $this->appName = $AppName;
+ $this->urlGenerator = $urlGenerator;
+
+ $this->logger = \OC::$server->getLogger();
+ $this->config = $config;
+ $this->trans = $trans;
+ $this->crypt = $crypt;
+ $this->groupManager = $groupManager;
+ $this->setInterval($this->config->GetEditorsCheckInterval());
+ }
+
+ /**
+ * Makes the background check
+ *
+ * @param array $argument unused argument
+ */
+ protected function run($argument) {
+ if (empty($this->config->GetDocumentServerUrl())) {
+ $this->logger->debug("Settings are empty", ["app" => $this->appName]);
+ return;
+ }
+ if (!$this->config->SettingsAreSuccessful()) {
+ $this->logger->debug("Settings are not correct", ["app" => $this->appName]);
+ return;
+ }
+ $fileUrl = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.emptyfile");
+ if (!$this->config->UseDemo() && !empty($this->config->GetStorageUrl())) {
+ $fileUrl = str_replace($this->urlGenerator->getAbsoluteURL("/"), $this->config->GetStorageUrl(), $fileUrl);
+ }
+ $host = parse_url($fileUrl)["host"];
+ if ($host === "localhost" || $host === "127.0.0.1") {
+ $this->logger->debug("Localhost is not alowed for cron editors availability check. Please provide server address for internal requests from ONLYOFFICE Docs", ["app" => $this->appName]);
+ return;
+ }
+
+ $this->logger->debug("ONLYOFFICE check started by cron", ["app" => $this->appName]);
+
+ $documentService = new DocumentService($this->trans, $this->config);
+ list($error, $version) = $documentService->checkDocServiceUrl($this->urlGenerator, $this->crypt);
+ if (!empty($error)) {
+ $this->logger->info("ONLYOFFICE server is not available", ["app" => $this->appName]);
+ $this->config->SetSettingsError($error);
+ $this->notifyAdmins();
+ } else {
+ $this->logger->debug("ONLYOFFICE server availability check is finished successfully", ["app" => $this->appName]);
+ }
+ }
+
+ /**
+ * Get the list of users to notify
+ *
+ * @return string[]
+ */
+ private function getUsersToNotify() {
+ $notifyGroups = ["admin"];
+ $notifyUsers = [];
+
+ foreach ($notifyGroups as $notifyGroup) {
+ $group = $this->groupManager->get($notifyGroup);
+ if ($group === null || !($group instanceof IGroup)) {
+ continue;
+ }
+ $users = $group->getUsers();
+ foreach ($users as $user) {
+ $notifyUsers[] = $user->getUID();
+ }
+ }
+ return $notifyUsers;
+ }
+
+ /**
+ * Send notification to admins
+ * @return void
+ */
+ private function notifyAdmins() {
+ $notificationManager = \OC::$server->getNotificationManager();
+ $notification = $notificationManager->createNotification();
+ $notification->setApp($this->appName)
+ ->setDateTime(new \DateTime())
+ ->setObject("editorsCheck", $this->trans->t("ONLYOFFICE server is not available"))
+ ->setSubject("editorscheck_info");
+ foreach ($this->getUsersToNotify() as $uid) {
+ $notification->setUser($uid);
+ $notificationManager->notify($notification);
+ }
+ }
}
diff --git a/lib/crypt.php b/lib/crypt.php
index 730b2932..692064c5 100644
--- a/lib/crypt.php
+++ b/lib/crypt.php
@@ -27,49 +27,49 @@
* @package OCA\Onlyoffice
*/
class Crypt {
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- private $config;
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ private $config;
- /**
- * @param AppConfig $config - application configutarion
- */
- public function __construct(AppConfig $appConfig) {
- $this->config = $appConfig;
- }
+ /**
+ * @param AppConfig $config - application configutarion
+ */
+ public function __construct(AppConfig $appConfig) {
+ $this->config = $appConfig;
+ }
- /**
- * Generate token for the object
- *
- * @param array $object - object to signature
- *
- * @return string
- */
- public function GetHash($object) {
- return \Firebase\JWT\JWT::encode($object, $this->config->GetSKey(), "HS256");
- }
+ /**
+ * Generate token for the object
+ *
+ * @param array $object - object to signature
+ *
+ * @return string
+ */
+ public function GetHash($object) {
+ return \Firebase\JWT\JWT::encode($object, $this->config->GetSKey(), "HS256");
+ }
- /**
- * Create an object from the token
- *
- * @param string $token - token
- *
- * @return array
- */
- public function ReadHash($token) {
- $result = null;
- $error = null;
- if ($token === null) {
- return [$result, "token is empty"];
- }
- try {
- $result = \Firebase\JWT\JWT::decode($token, new \Firebase\JWT\Key($this->config->GetSKey(), "HS256"));
- } catch (\UnexpectedValueException $e) {
- $error = $e->getMessage();
- }
- return [$result, $error];
- }
+ /**
+ * Create an object from the token
+ *
+ * @param string $token - token
+ *
+ * @return array
+ */
+ public function ReadHash($token) {
+ $result = null;
+ $error = null;
+ if ($token === null) {
+ return [$result, "token is empty"];
+ }
+ try {
+ $result = \Firebase\JWT\JWT::decode($token, new \Firebase\JWT\Key($this->config->GetSKey(), "HS256"));
+ } catch (\UnexpectedValueException $e) {
+ $error = $e->getMessage();
+ }
+ return [$result, $error];
+ }
}
diff --git a/lib/documentservice.php b/lib/documentservice.php
index 73828716..88e59f8c 100644
--- a/lib/documentservice.php
+++ b/lib/documentservice.php
@@ -29,414 +29,414 @@
* @package OCA\Onlyoffice
*/
class DocumentService {
- /**
- * Application name
- *
- * @var string
- */
- private static $appName = "onlyoffice";
-
- /**
- * l10n service
- *
- * @var IL10N
- */
- private $trans;
-
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- private $config;
-
- /**
- * @param IL10N $trans - l10n service
- * @param AppConfig $config - application configutarion
- */
- public function __construct(IL10N $trans, AppConfig $appConfig) {
- $this->trans = $trans;
- $this->config = $appConfig;
- }
-
- /**
- * 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);
- }
- $key = preg_replace("[^0-9-.a-zA-Z_=]", "_", $expected_key);
- $key = substr($key, 0, min([\strlen($key), 20]));
- return $key;
- }
-
- /**
- * The method is to convert the file to the required format and return the result url
- *
- * @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
- *
- * @return string
- */
- public function GetConvertedUri($document_uri, $from_extension, $to_extension, $document_revision_id) {
- $responceFromConvertService = $this->SendRequestToConvertService($document_uri, $from_extension, $to_extension, $document_revision_id, false);
-
- $errorElement = $responceFromConvertService->Error;
- if ($errorElement->count() > 0) {
- $this->ProcessConvServResponceError($errorElement . "");
- }
-
- $isEndConvert = $responceFromConvertService->EndConvert;
-
- if ($isEndConvert !== null && strtolower($isEndConvert) === "true") {
- return (string)$responceFromConvertService->FileUrl;
- }
-
- return "";
- }
-
- /**
- * 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
- */
- public function SendRequestToConvertService($document_uri, $from_extension, $to_extension, $document_revision_id, $is_async) {
- $documentServerUrl = $this->config->GetDocumentServerInternalUrl();
-
- if (empty($documentServerUrl)) {
- throw new \Exception($this->trans->t("ONLYOFFICE app is not configured. Please contact admin"));
- }
-
- $urlToConverter = $documentServerUrl . "ConvertService.ashx";
-
- if (empty($document_revision_id)) {
- $document_revision_id = $document_uri;
- }
-
- $document_revision_id = self::GenerateRevisionId($document_revision_id);
-
- if (empty($from_extension)) {
- $from_extension = pathinfo($document_uri)["extension"];
- } else {
- $from_extension = trim($from_extension, ".");
- }
-
- $data = [
- "async" => $is_async,
- "url" => $document_uri,
- "outputtype" => trim($to_extension, "."),
- "filetype" => $from_extension,
- "title" => $document_revision_id . "." . $from_extension,
- "key" => $document_revision_id,
- "region" => str_replace("_", "-", \OC::$server->getL10NFactory("")->get("")->getLanguageCode())
- ];
-
- if ($this->config->UseDemo()) {
- $data["tenant"] = $this->config->GetSystemValue("instanceid", true);
- }
-
- $opts = [
- "timeout" => "120",
- "headers" => [
- "Content-type" => "application/json"
- ],
- "body" => json_encode($data)
- ];
-
- if (!empty($this->config->GetDocumentServerSecret())) {
- $params = [
- "payload" => $data
- ];
- $token = \Firebase\JWT\JWT::encode($params, $this->config->GetDocumentServerSecret(), "HS256");
- $opts["headers"][$this->config->JwtHeader()] = "Bearer " . $token;
-
- $token = \Firebase\JWT\JWT::encode($data, $this->config->GetDocumentServerSecret(), "HS256");
- $data["token"] = $token;
- $opts["body"] = json_encode($data);
- }
-
- $response_xml_data = $this->Request($urlToConverter, "post", $opts);
-
- libxml_use_internal_errors(true);
- if (!\function_exists("simplexml_load_file")) {
- throw new \Exception($this->trans->t("Server can't read xml"));
- }
- $response_data = simplexml_load_string($response_xml_data);
- if (!$response_data) {
- $exc = $this->trans->t("Bad Response. Errors: ");
- foreach (libxml_get_errors() as $error) {
- $exc = $exc . "\t" . $error->message;
- }
- throw new \Exception($exc);
- }
-
- return $response_data;
- }
-
- /**
- * Generate an error code table of convertion
- *
- * @param string $errorCode - Error code
- *
- * @return null
- */
- public function ProcessConvServResponceError($errorCode) {
- $errorMessageTemplate = $this->trans->t("Error occurred in the document service");
- $errorMessage = "";
-
- switch ($errorCode) {
- case -20:
- $errorMessage = $errorMessageTemplate . ": Error encrypt signature";
- break;
- case -8:
- $errorMessage = $errorMessageTemplate . ": Invalid token";
- break;
- case -7:
- $errorMessage = $errorMessageTemplate . ": Error document request";
- break;
- case -6:
- $errorMessage = $errorMessageTemplate . ": Error while accessing the conversion result database";
- break;
- case -5:
- $errorMessage = $errorMessageTemplate . ": Incorrect password";
- break;
- case -4:
- $errorMessage = $errorMessageTemplate . ": Error while downloading the document file to be converted.";
- break;
- case -3:
- $errorMessage = $errorMessageTemplate . ": Conversion error";
- break;
- case -2:
- $errorMessage = $errorMessageTemplate . ": Timeout conversion error";
- break;
- case -1:
- $errorMessage = $errorMessageTemplate . ": Unknown error";
- break;
- case 0:
- break;
- default:
- $errorMessage = $errorMessageTemplate . ": ErrorCode = " . $errorCode;
- break;
- }
-
- throw new \Exception($errorMessage);
- }
-
- /**
- * Request health status
- *
- * @return bool
- */
- public function HealthcheckRequest() {
- $documentServerUrl = $this->config->GetDocumentServerInternalUrl();
-
- if (empty($documentServerUrl)) {
- throw new \Exception($this->trans->t("ONLYOFFICE app is not configured. Please contact admin"));
- }
-
- $urlHealthcheck = $documentServerUrl . "healthcheck";
-
- $response = $this->Request($urlHealthcheck);
-
- return $response === "true";
- }
-
- /**
- * Send command
- *
- * @param string $method - type of command
- *
- * @return array
- */
- public function CommandRequest($method) {
- $documentServerUrl = $this->config->GetDocumentServerInternalUrl();
-
- if (empty($documentServerUrl)) {
- throw new \Exception($this->trans->t("ONLYOFFICE app is not configured. Please contact admin"));
- }
-
- $urlCommand = $documentServerUrl . "coauthoring/CommandService.ashx";
-
- $data = [
- "c" => $method
- ];
-
- $opts = [
- "headers" => [
- "Content-type" => "application/json"
- ],
- "body" => json_encode($data)
- ];
-
- if (!empty($this->config->GetDocumentServerSecret())) {
- $params = [
- "payload" => $data
- ];
- $token = \Firebase\JWT\JWT::encode($params, $this->config->GetDocumentServerSecret(), "HS256");
- $opts["headers"][$this->config->JwtHeader()] = "Bearer " . $token;
-
- $token = \Firebase\JWT\JWT::encode($data, $this->config->GetDocumentServerSecret(), "HS256");
- $data["token"] = $token;
- $opts["body"] = json_encode($data);
- }
-
- $response = $this->Request($urlCommand, "post", $opts);
-
- $data = json_decode($response);
-
- $this->ProcessCommandServResponceError($data->error);
-
- return $data;
- }
-
- /**
- * Generate an error code table of command
- *
- * @param string $errorCode - Error code
- *
- * @return null
- */
- public 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);
- }
-
- /**
- * Request to Document Server with turn off verification
- *
- * @param string $url - request address
- * @param array $method - request method
- * @param array $opts - request options
- *
- * @return string
- */
- public function Request($url, $method = "get", $opts = null) {
- $httpClientService = \OC::$server->getHTTPClientService();
- $client = $httpClientService->newClient();
-
- if ($opts === null) {
- $opts = [];
- }
- if (substr($url, 0, \strlen("https")) === "https" && $this->config->GetVerifyPeerOff()) {
- $opts["verify"] = false;
- }
- if (!\array_key_exists("timeout", $opts)) {
- $opts["timeout"] = 60;
- }
-
- if ($method === "post") {
- $response = $client->post($url, $opts);
- } else {
- $response = $client->get($url, $opts);
- }
-
- return $response->getBody();
- }
-
- /**
- * Checking document service location
- *
- * @param OCP\IURLGenerator $urlGenerator - url generator
- * @param OCA\Onlyoffice\Crypt $crypt -crypt
- *
- * @return array
- */
- public function checkDocServiceUrl($urlGenerator, $crypt) {
- $logger = \OC::$server->getLogger();
- $version = null;
-
- try {
- if (preg_match("/^https:\/\//i", $urlGenerator->getAbsoluteURL("/"))
- && preg_match("/^http:\/\//i", $this->config->GetDocumentServerUrl())) {
- throw new \Exception($this->trans->t("Mixed Active Content is not allowed. HTTPS address for ONLYOFFICE Docs is required."));
- }
- } catch (\Exception $e) {
- $logger->logException($e, ["message" => "Protocol on check error", "app" => self::$appName]);
- return [$e->getMessage(), $version];
- }
-
- try {
- $healthcheckResponse = $this->HealthcheckRequest();
- if (!$healthcheckResponse) {
- throw new \Exception($this->trans->t("Bad healthcheck status"));
- }
- } catch (\Exception $e) {
- $logger->logException($e, ["message" => "HealthcheckRequest on check error", "app" => self::$appName]);
- return [$e->getMessage(), $version];
- }
-
- try {
- $commandResponse = $this->CommandRequest("version");
-
- $logger->debug("CommandRequest on check: " . json_encode($commandResponse), ["app" => self::$appName]);
-
- if (empty($commandResponse)) {
- throw new \Exception($this->trans->t("Error occurred in the document service"));
- }
-
- $version = $commandResponse->version;
- $versionF = \floatval($version);
- if ($versionF > 0.0 && $versionF <= 6.0) {
- throw new \Exception($this->trans->t("Not supported version"));
- }
- } catch (\Exception $e) {
- $logger->logException($e, ["message" => "CommandRequest on check error", "app" => self::$appName]);
- return [$e->getMessage(), $version];
- }
-
- $convertedFileUri = null;
- try {
- $hashUrl = $crypt->GetHash(["action" => "empty"]);
- $fileUrl = $urlGenerator->linkToRouteAbsolute(self::$appName . ".callback.emptyfile", ["doc" => $hashUrl]);
- if (!$this->config->UseDemo() && !empty($this->config->GetStorageUrl())) {
- $fileUrl = str_replace($urlGenerator->getAbsoluteURL("/"), $this->config->GetStorageUrl(), $fileUrl);
- }
-
- $convertedFileUri = $this->GetConvertedUri($fileUrl, "docx", "docx", "check_" . rand());
- } catch (\Exception $e) {
- $logger->logException($e, ["message" => "GetConvertedUri on check error", "app" => self::$appName]);
- return [$e->getMessage(), $version];
- }
-
- try {
- $this->Request($convertedFileUri);
- } catch (\Exception $e) {
- $logger->logException($e, ["message" => "Request converted file on check error", "app" => self::$appName]);
- return [$e->getMessage(), $version];
- }
-
- return ["", $version];
- }
+ /**
+ * Application name
+ *
+ * @var string
+ */
+ private static $appName = "onlyoffice";
+
+ /**
+ * l10n service
+ *
+ * @var IL10N
+ */
+ private $trans;
+
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ private $config;
+
+ /**
+ * @param IL10N $trans - l10n service
+ * @param AppConfig $config - application configutarion
+ */
+ public function __construct(IL10N $trans, AppConfig $appConfig) {
+ $this->trans = $trans;
+ $this->config = $appConfig;
+ }
+
+ /**
+ * 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);
+ }
+ $key = preg_replace("[^0-9-.a-zA-Z_=]", "_", $expected_key);
+ $key = substr($key, 0, min([\strlen($key), 20]));
+ return $key;
+ }
+
+ /**
+ * The method is to convert the file to the required format and return the result url
+ *
+ * @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
+ *
+ * @return string
+ */
+ public function GetConvertedUri($document_uri, $from_extension, $to_extension, $document_revision_id) {
+ $responceFromConvertService = $this->SendRequestToConvertService($document_uri, $from_extension, $to_extension, $document_revision_id, false);
+
+ $errorElement = $responceFromConvertService->Error;
+ if ($errorElement->count() > 0) {
+ $this->ProcessConvServResponceError($errorElement . "");
+ }
+
+ $isEndConvert = $responceFromConvertService->EndConvert;
+
+ if ($isEndConvert !== null && strtolower($isEndConvert) === "true") {
+ return (string)$responceFromConvertService->FileUrl;
+ }
+
+ return "";
+ }
+
+ /**
+ * 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
+ */
+ public function SendRequestToConvertService($document_uri, $from_extension, $to_extension, $document_revision_id, $is_async) {
+ $documentServerUrl = $this->config->GetDocumentServerInternalUrl();
+
+ if (empty($documentServerUrl)) {
+ throw new \Exception($this->trans->t("ONLYOFFICE app is not configured. Please contact admin"));
+ }
+
+ $urlToConverter = $documentServerUrl . "ConvertService.ashx";
+
+ if (empty($document_revision_id)) {
+ $document_revision_id = $document_uri;
+ }
+
+ $document_revision_id = self::GenerateRevisionId($document_revision_id);
+
+ if (empty($from_extension)) {
+ $from_extension = pathinfo($document_uri)["extension"];
+ } else {
+ $from_extension = trim($from_extension, ".");
+ }
+
+ $data = [
+ "async" => $is_async,
+ "url" => $document_uri,
+ "outputtype" => trim($to_extension, "."),
+ "filetype" => $from_extension,
+ "title" => $document_revision_id . "." . $from_extension,
+ "key" => $document_revision_id,
+ "region" => str_replace("_", "-", \OC::$server->getL10NFactory("")->get("")->getLanguageCode())
+ ];
+
+ if ($this->config->UseDemo()) {
+ $data["tenant"] = $this->config->GetSystemValue("instanceid", true);
+ }
+
+ $opts = [
+ "timeout" => "120",
+ "headers" => [
+ "Content-type" => "application/json"
+ ],
+ "body" => json_encode($data)
+ ];
+
+ if (!empty($this->config->GetDocumentServerSecret())) {
+ $params = [
+ "payload" => $data
+ ];
+ $token = \Firebase\JWT\JWT::encode($params, $this->config->GetDocumentServerSecret(), "HS256");
+ $opts["headers"][$this->config->JwtHeader()] = "Bearer " . $token;
+
+ $token = \Firebase\JWT\JWT::encode($data, $this->config->GetDocumentServerSecret(), "HS256");
+ $data["token"] = $token;
+ $opts["body"] = json_encode($data);
+ }
+
+ $response_xml_data = $this->Request($urlToConverter, "post", $opts);
+
+ libxml_use_internal_errors(true);
+ if (!\function_exists("simplexml_load_file")) {
+ throw new \Exception($this->trans->t("Server can't read xml"));
+ }
+ $response_data = simplexml_load_string($response_xml_data);
+ if (!$response_data) {
+ $exc = $this->trans->t("Bad Response. Errors: ");
+ foreach (libxml_get_errors() as $error) {
+ $exc = $exc . "\t" . $error->message;
+ }
+ throw new \Exception($exc);
+ }
+
+ return $response_data;
+ }
+
+ /**
+ * Generate an error code table of convertion
+ *
+ * @param string $errorCode - Error code
+ *
+ * @return null
+ */
+ public function ProcessConvServResponceError($errorCode) {
+ $errorMessageTemplate = $this->trans->t("Error occurred in the document service");
+ $errorMessage = "";
+
+ switch ($errorCode) {
+ case -20:
+ $errorMessage = $errorMessageTemplate . ": Error encrypt signature";
+ break;
+ case -8:
+ $errorMessage = $errorMessageTemplate . ": Invalid token";
+ break;
+ case -7:
+ $errorMessage = $errorMessageTemplate . ": Error document request";
+ break;
+ case -6:
+ $errorMessage = $errorMessageTemplate . ": Error while accessing the conversion result database";
+ break;
+ case -5:
+ $errorMessage = $errorMessageTemplate . ": Incorrect password";
+ break;
+ case -4:
+ $errorMessage = $errorMessageTemplate . ": Error while downloading the document file to be converted.";
+ break;
+ case -3:
+ $errorMessage = $errorMessageTemplate . ": Conversion error";
+ break;
+ case -2:
+ $errorMessage = $errorMessageTemplate . ": Timeout conversion error";
+ break;
+ case -1:
+ $errorMessage = $errorMessageTemplate . ": Unknown error";
+ break;
+ case 0:
+ break;
+ default:
+ $errorMessage = $errorMessageTemplate . ": ErrorCode = " . $errorCode;
+ break;
+ }
+
+ throw new \Exception($errorMessage);
+ }
+
+ /**
+ * Request health status
+ *
+ * @return bool
+ */
+ public function HealthcheckRequest() {
+ $documentServerUrl = $this->config->GetDocumentServerInternalUrl();
+
+ if (empty($documentServerUrl)) {
+ throw new \Exception($this->trans->t("ONLYOFFICE app is not configured. Please contact admin"));
+ }
+
+ $urlHealthcheck = $documentServerUrl . "healthcheck";
+
+ $response = $this->Request($urlHealthcheck);
+
+ return $response === "true";
+ }
+
+ /**
+ * Send command
+ *
+ * @param string $method - type of command
+ *
+ * @return array
+ */
+ public function CommandRequest($method) {
+ $documentServerUrl = $this->config->GetDocumentServerInternalUrl();
+
+ if (empty($documentServerUrl)) {
+ throw new \Exception($this->trans->t("ONLYOFFICE app is not configured. Please contact admin"));
+ }
+
+ $urlCommand = $documentServerUrl . "coauthoring/CommandService.ashx";
+
+ $data = [
+ "c" => $method
+ ];
+
+ $opts = [
+ "headers" => [
+ "Content-type" => "application/json"
+ ],
+ "body" => json_encode($data)
+ ];
+
+ if (!empty($this->config->GetDocumentServerSecret())) {
+ $params = [
+ "payload" => $data
+ ];
+ $token = \Firebase\JWT\JWT::encode($params, $this->config->GetDocumentServerSecret(), "HS256");
+ $opts["headers"][$this->config->JwtHeader()] = "Bearer " . $token;
+
+ $token = \Firebase\JWT\JWT::encode($data, $this->config->GetDocumentServerSecret(), "HS256");
+ $data["token"] = $token;
+ $opts["body"] = json_encode($data);
+ }
+
+ $response = $this->Request($urlCommand, "post", $opts);
+
+ $data = json_decode($response);
+
+ $this->ProcessCommandServResponceError($data->error);
+
+ return $data;
+ }
+
+ /**
+ * Generate an error code table of command
+ *
+ * @param string $errorCode - Error code
+ *
+ * @return null
+ */
+ public 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);
+ }
+
+ /**
+ * Request to Document Server with turn off verification
+ *
+ * @param string $url - request address
+ * @param array $method - request method
+ * @param array $opts - request options
+ *
+ * @return string
+ */
+ public function Request($url, $method = "get", $opts = null) {
+ $httpClientService = \OC::$server->getHTTPClientService();
+ $client = $httpClientService->newClient();
+
+ if ($opts === null) {
+ $opts = [];
+ }
+ if (substr($url, 0, \strlen("https")) === "https" && $this->config->GetVerifyPeerOff()) {
+ $opts["verify"] = false;
+ }
+ if (!\array_key_exists("timeout", $opts)) {
+ $opts["timeout"] = 60;
+ }
+
+ if ($method === "post") {
+ $response = $client->post($url, $opts);
+ } else {
+ $response = $client->get($url, $opts);
+ }
+
+ return $response->getBody();
+ }
+
+ /**
+ * Checking document service location
+ *
+ * @param OCP\IURLGenerator $urlGenerator - url generator
+ * @param OCA\Onlyoffice\Crypt $crypt -crypt
+ *
+ * @return array
+ */
+ public function checkDocServiceUrl($urlGenerator, $crypt) {
+ $logger = \OC::$server->getLogger();
+ $version = null;
+
+ try {
+ if (preg_match("/^https:\/\//i", $urlGenerator->getAbsoluteURL("/"))
+ && preg_match("/^http:\/\//i", $this->config->GetDocumentServerUrl())) {
+ throw new \Exception($this->trans->t("Mixed Active Content is not allowed. HTTPS address for ONLYOFFICE Docs is required."));
+ }
+ } catch (\Exception $e) {
+ $logger->logException($e, ["message" => "Protocol on check error", "app" => self::$appName]);
+ return [$e->getMessage(), $version];
+ }
+
+ try {
+ $healthcheckResponse = $this->HealthcheckRequest();
+ if (!$healthcheckResponse) {
+ throw new \Exception($this->trans->t("Bad healthcheck status"));
+ }
+ } catch (\Exception $e) {
+ $logger->logException($e, ["message" => "HealthcheckRequest on check error", "app" => self::$appName]);
+ return [$e->getMessage(), $version];
+ }
+
+ try {
+ $commandResponse = $this->CommandRequest("version");
+
+ $logger->debug("CommandRequest on check: " . json_encode($commandResponse), ["app" => self::$appName]);
+
+ if (empty($commandResponse)) {
+ throw new \Exception($this->trans->t("Error occurred in the document service"));
+ }
+
+ $version = $commandResponse->version;
+ $versionF = \floatval($version);
+ if ($versionF > 0.0 && $versionF <= 6.0) {
+ throw new \Exception($this->trans->t("Not supported version"));
+ }
+ } catch (\Exception $e) {
+ $logger->logException($e, ["message" => "CommandRequest on check error", "app" => self::$appName]);
+ return [$e->getMessage(), $version];
+ }
+
+ $convertedFileUri = null;
+ try {
+ $hashUrl = $crypt->GetHash(["action" => "empty"]);
+ $fileUrl = $urlGenerator->linkToRouteAbsolute(self::$appName . ".callback.emptyfile", ["doc" => $hashUrl]);
+ if (!$this->config->UseDemo() && !empty($this->config->GetStorageUrl())) {
+ $fileUrl = str_replace($urlGenerator->getAbsoluteURL("/"), $this->config->GetStorageUrl(), $fileUrl);
+ }
+
+ $convertedFileUri = $this->GetConvertedUri($fileUrl, "docx", "docx", "check_" . rand());
+ } catch (\Exception $e) {
+ $logger->logException($e, ["message" => "GetConvertedUri on check error", "app" => self::$appName]);
+ return [$e->getMessage(), $version];
+ }
+
+ try {
+ $this->Request($convertedFileUri);
+ } catch (\Exception $e) {
+ $logger->logException($e, ["message" => "Request converted file on check error", "app" => self::$appName]);
+ return [$e->getMessage(), $version];
+ }
+
+ return ["", $version];
+ }
}
diff --git a/lib/fileutility.php b/lib/fileutility.php
index 3233511e..d413484a 100644
--- a/lib/fileutility.php
+++ b/lib/fileutility.php
@@ -38,260 +38,260 @@
* @package OCA\Onlyoffice
*/
class FileUtility {
- /**
- * Application name
- *
- * @var string
- */
- private $appName;
-
- /**
- * l10n service
- *
- * @var IL10N
- */
- private $trans;
-
- /**
- * Logger
- *
- * @var ILogger
- */
- private $logger;
-
- /**
- * Share manager
- *
- * @var IManager
- */
- private $shareManager;
-
- /**
- * Session
- *
- * @var ISession
- */
- private $session;
-
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- private $config;
-
- /**
- * @param string $AppName - application name
- * @param IL10N $trans - l10n service
- * @param ILogger $logger - logger
- * @param AppConfig $config - application configuration
- * @param IManager $shareManager - Share manager
- * @param IManager $ISession - Session
- */
- public function __construct(
- $AppName,
- IL10N $trans,
- ILogger $logger,
- AppConfig $config,
- IManager $shareManager,
- ISession $session
- ) {
- $this->appName = $AppName;
- $this->trans = $trans;
- $this->logger = $logger;
- $this->config = $config;
- $this->shareManager = $shareManager;
- $this->session = $session;
- }
-
- /**
- * Getting file by token
- *
- * @param integer $fileId - file identifier
- * @param string $shareToken - access token
- * @param string $path - file path
- *
- * @return array
- */
- public function getFileByToken($fileId, $shareToken, $path = null) {
- list($node, $error, $share) = $this->getNodeByToken($shareToken);
-
- if (isset($error)) {
- return [null, $error, null];
- }
-
- if ($node instanceof Folder) {
- if ($fileId !== null && $fileId !== 0) {
- try {
- $files = $node->getById($fileId);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "getFileByToken: $fileId", "app" => $this->appName]);
- return [null, $this->trans->t("Invalid request"), null];
- }
-
- if (empty($files)) {
- $this->logger->info("Files not found: $fileId", ["app" => $this->appName]);
- return [null, $this->trans->t("File not found"), null];
- }
- $file = $files[0];
- } else {
- try {
- $file = $node->get($path);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "getFileByToken for path: $path", "app" => $this->appName]);
- return [null, $this->trans->t("Invalid request"), null];
- }
- }
- } else {
- $file = $node;
- }
-
- return [$file, null, $share];
- }
-
- /**
- * Getting file by token
- *
- * @param string $shareToken - access token
- *
- * @return array
- */
- public function getNodeByToken($shareToken) {
- list($share, $error) = $this->getShare($shareToken);
-
- if (isset($error)) {
- return [null, $error, null];
- }
-
- if (($share->getPermissions() & Constants::PERMISSION_READ) === 0) {
- return [null, $this->trans->t("You do not have enough permissions to view the file"), null];
- }
-
- try {
- $node = $share->getNode();
- } catch (NotFoundException $e) {
- $this->logger->logException($e, ["message" => "getNodeByToken error", "app" => $this->appName]);
- return [null, $this->trans->t("File not found"), null];
- }
-
- return [$node, null, $share];
- }
-
- /**
- * Getting share by token
- *
- * @param string $shareToken - access token
- *
- * @return array
- */
- public function getShare($shareToken) {
- if (empty($shareToken)) {
- return [null, $this->trans->t("FileId is empty")];
- }
-
- $share = null;
- try {
- $share = $this->shareManager->getShareByToken($shareToken);
- } catch (ShareNotFound $e) {
- $this->logger->logException($e, ["message" => "getShare error", "app" => $this->appName]);
- $share = null;
- }
-
- if ($share === null || $share === false) {
- return [null, $this->trans->t("You do not have enough permissions to view the file")];
- }
-
- if ($share->getPassword()
- && (!$this->session->exists("public_link_authenticated")
- || $this->session->get("public_link_authenticated") !== (string) $share->getId())) {
- return [null, $this->trans->t("You do not have enough permissions to view the file")];
- }
-
- return [$share, null];
- }
-
- /**
- * Generate unique document identifier
- *
- * @param File $file - file
- * @param bool $origin - request from federated store
- *
- * @return string
- */
- public function getKey($file, $origin = false) {
- $fileId = $file->getId();
-
- if ($origin
- && RemoteInstance::isRemoteFile($file)) {
- $key = RemoteInstance::getRemoteKey($file);
- if (!empty($key)) {
- return $key;
- }
- }
-
- $key = KeyManager::get($fileId);
-
- if (empty($key)) {
- $instanceId = $this->config->GetSystemValue("instanceid", true);
-
- $key = $instanceId . "_" . $this->GUID();
-
- KeyManager::set($fileId, $key);
- }
-
- return $key;
- }
-
- /**
- * Detected attribute permission for shared file
- *
- * @param File $file - file
- * @param string $attribute - request from federated store
- *
- * @return bool
- */
- public function hasPermissionAttribute($file, $attribute = "download") {
- $fileStorage = $file->getStorage();
- if ($fileStorage->instanceOfStorage("\OCA\Files_Sharing\SharedStorage")) {
- $storageShare = $fileStorage->getShare();
- if (method_exists($storageShare, "getAttributes")) {
- $attributes = $storageShare->getAttributes();
-
- $permissionsDownload = $attributes->getAttribute("permissions", "download");
- if ($permissionsDownload !== null && $permissionsDownload !== true) {
- return false;
- }
- }
- }
-
- return true;
- }
-
- /**
- * Generate unique identifier
- *
- * @return string
- */
- private function GUID() {
- if (\function_exists("com_create_guid") === true) {
- return trim(com_create_guid(), "{}");
- }
-
- return sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
- }
-
- /**
- * Generate unique file version key
- *
- * @param Version $version - file version
- *
- * @return string
- */
- public function getVersionKey($version) {
- $instanceId = $this->config->GetSystemValue("instanceid", true);
-
- $key = $instanceId . "_" . $version->getSourceFile()->getEtag() . "_" . $version->getRevisionId();
-
- return $key;
- }
+ /**
+ * Application name
+ *
+ * @var string
+ */
+ private $appName;
+
+ /**
+ * l10n service
+ *
+ * @var IL10N
+ */
+ private $trans;
+
+ /**
+ * Logger
+ *
+ * @var ILogger
+ */
+ private $logger;
+
+ /**
+ * Share manager
+ *
+ * @var IManager
+ */
+ private $shareManager;
+
+ /**
+ * Session
+ *
+ * @var ISession
+ */
+ private $session;
+
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ private $config;
+
+ /**
+ * @param string $AppName - application name
+ * @param IL10N $trans - l10n service
+ * @param ILogger $logger - logger
+ * @param AppConfig $config - application configuration
+ * @param IManager $shareManager - Share manager
+ * @param IManager $ISession - Session
+ */
+ public function __construct(
+ $AppName,
+ IL10N $trans,
+ ILogger $logger,
+ AppConfig $config,
+ IManager $shareManager,
+ ISession $session
+ ) {
+ $this->appName = $AppName;
+ $this->trans = $trans;
+ $this->logger = $logger;
+ $this->config = $config;
+ $this->shareManager = $shareManager;
+ $this->session = $session;
+ }
+
+ /**
+ * Getting file by token
+ *
+ * @param integer $fileId - file identifier
+ * @param string $shareToken - access token
+ * @param string $path - file path
+ *
+ * @return array
+ */
+ public function getFileByToken($fileId, $shareToken, $path = null) {
+ list($node, $error, $share) = $this->getNodeByToken($shareToken);
+
+ if (isset($error)) {
+ return [null, $error, null];
+ }
+
+ if ($node instanceof Folder) {
+ if ($fileId !== null && $fileId !== 0) {
+ try {
+ $files = $node->getById($fileId);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "getFileByToken: $fileId", "app" => $this->appName]);
+ return [null, $this->trans->t("Invalid request"), null];
+ }
+
+ if (empty($files)) {
+ $this->logger->info("Files not found: $fileId", ["app" => $this->appName]);
+ return [null, $this->trans->t("File not found"), null];
+ }
+ $file = $files[0];
+ } else {
+ try {
+ $file = $node->get($path);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "getFileByToken for path: $path", "app" => $this->appName]);
+ return [null, $this->trans->t("Invalid request"), null];
+ }
+ }
+ } else {
+ $file = $node;
+ }
+
+ return [$file, null, $share];
+ }
+
+ /**
+ * Getting file by token
+ *
+ * @param string $shareToken - access token
+ *
+ * @return array
+ */
+ public function getNodeByToken($shareToken) {
+ list($share, $error) = $this->getShare($shareToken);
+
+ if (isset($error)) {
+ return [null, $error, null];
+ }
+
+ if (($share->getPermissions() & Constants::PERMISSION_READ) === 0) {
+ return [null, $this->trans->t("You do not have enough permissions to view the file"), null];
+ }
+
+ try {
+ $node = $share->getNode();
+ } catch (NotFoundException $e) {
+ $this->logger->logException($e, ["message" => "getNodeByToken error", "app" => $this->appName]);
+ return [null, $this->trans->t("File not found"), null];
+ }
+
+ return [$node, null, $share];
+ }
+
+ /**
+ * Getting share by token
+ *
+ * @param string $shareToken - access token
+ *
+ * @return array
+ */
+ public function getShare($shareToken) {
+ if (empty($shareToken)) {
+ return [null, $this->trans->t("FileId is empty")];
+ }
+
+ $share = null;
+ try {
+ $share = $this->shareManager->getShareByToken($shareToken);
+ } catch (ShareNotFound $e) {
+ $this->logger->logException($e, ["message" => "getShare error", "app" => $this->appName]);
+ $share = null;
+ }
+
+ if ($share === null || $share === false) {
+ return [null, $this->trans->t("You do not have enough permissions to view the file")];
+ }
+
+ if ($share->getPassword()
+ && (!$this->session->exists("public_link_authenticated")
+ || $this->session->get("public_link_authenticated") !== (string) $share->getId())) {
+ return [null, $this->trans->t("You do not have enough permissions to view the file")];
+ }
+
+ return [$share, null];
+ }
+
+ /**
+ * Generate unique document identifier
+ *
+ * @param File $file - file
+ * @param bool $origin - request from federated store
+ *
+ * @return string
+ */
+ public function getKey($file, $origin = false) {
+ $fileId = $file->getId();
+
+ if ($origin
+ && RemoteInstance::isRemoteFile($file)) {
+ $key = RemoteInstance::getRemoteKey($file);
+ if (!empty($key)) {
+ return $key;
+ }
+ }
+
+ $key = KeyManager::get($fileId);
+
+ if (empty($key)) {
+ $instanceId = $this->config->GetSystemValue("instanceid", true);
+
+ $key = $instanceId . "_" . $this->GUID();
+
+ KeyManager::set($fileId, $key);
+ }
+
+ return $key;
+ }
+
+ /**
+ * Detected attribute permission for shared file
+ *
+ * @param File $file - file
+ * @param string $attribute - request from federated store
+ *
+ * @return bool
+ */
+ public function hasPermissionAttribute($file, $attribute = "download") {
+ $fileStorage = $file->getStorage();
+ if ($fileStorage->instanceOfStorage("\OCA\Files_Sharing\SharedStorage")) {
+ $storageShare = $fileStorage->getShare();
+ if (method_exists($storageShare, "getAttributes")) {
+ $attributes = $storageShare->getAttributes();
+
+ $permissionsDownload = $attributes->getAttribute("permissions", "download");
+ if ($permissionsDownload !== null && $permissionsDownload !== true) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Generate unique identifier
+ *
+ * @return string
+ */
+ private function GUID() {
+ if (\function_exists("com_create_guid") === true) {
+ return trim(com_create_guid(), "{}");
+ }
+
+ return sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
+ }
+
+ /**
+ * Generate unique file version key
+ *
+ * @param Version $version - file version
+ *
+ * @return string
+ */
+ public function getVersionKey($version) {
+ $instanceId = $this->config->GetSystemValue("instanceid", true);
+
+ $key = $instanceId . "_" . $version->getSourceFile()->getEtag() . "_" . $version->getRevisionId();
+
+ return $key;
+ }
}
diff --git a/lib/fileversions.php b/lib/fileversions.php
index e690f1f3..957271c1 100644
--- a/lib/fileversions.php
+++ b/lib/fileversions.php
@@ -34,444 +34,444 @@
* @package OCA\Onlyoffice
*/
class FileVersions {
- /**
- * Application name
- *
- * @var string
- */
- private static $appName = "onlyoffice";
-
- /**
- * Changes file extension
- *
- * @var string
- */
- private static $changesExt = ".zip";
-
- /**
- * History file extension
- *
- * @var string
- */
- private static $historyExt = ".json";
-
- /**
- * File name contain author
- *
- * @var string
- */
- private static $authorExt = "_author.json";
-
- /**
- * Split file path and version id
- *
- * @param string $pathVersion - version path
- *
- * @return array
- */
- public static function splitPathVersion($pathVersion) {
- $pos = strrpos($pathVersion, ".v");
- if ($pos === false) {
- return false;
- }
- $filePath = substr($pathVersion, 0, $pos);
- $versionId = substr($pathVersion, 2 + $pos - \strlen($pathVersion));
- return [$filePath, $versionId];
- }
-
- /**
- * Check if folder is not exist
- *
- * @param View $view - view
- * @param string $path - folder path
- * @param bool $createIfNotExist - create folder if not exist
- *
- * @return bool
- */
- private static function checkFolderExist($view, $path, $createIfNotExist = false) {
- if ($view->is_dir($path)) {
- return true;
- }
- if (!$createIfNotExist) {
- return false;
- }
- $view->mkdir($path);
- return true;
- }
-
- /**
- * Get view and path for changes
- *
- * @param string $userId - user id
- * @param string $fileId - file id
- * @param bool $createIfNotExist - create folder if not exist
- *
- * @return array
- */
- private static function getView($userId, $fileId, $createIfNotExist = false) {
- $view = new View("/" . $userId);
-
- $path = self::$appName;
- if (!self::checkFolderExist($view, $path, $createIfNotExist)) {
- return [null, null];
- }
-
- if ($fileId === null) {
- return [$view, $path];
- }
-
- $path = $path . "/" . $fileId;
- if (!self::checkFolderExist($view, $path, $createIfNotExist)) {
- return [null, null];
- }
-
- return [$view, $path];
- }
-
- /**
- * Get changes from stored to history object
- *
- * @param string $ownerId - file owner id
- * @param string $fileId - file id
- * @param string $versionId - file version
- * @param string $prevVersion - previous version for check
- *
- * @return array
- */
- public static function getHistoryData($ownerId, $fileId, $versionId, $prevVersion) {
- $logger = \OC::$server->getLogger();
-
- if ($ownerId === null || $fileId === null) {
- return null;
- }
-
- list($view, $path) = self::getView($ownerId, $fileId);
- if ($view === null) {
- return null;
- }
-
- $historyPath = $path . "/" . $versionId . self::$historyExt;
- if (!$view->file_exists($historyPath)) {
- return null;
- }
-
- $historyDataString = $view->file_get_contents($historyPath);
-
- try {
- $historyData = json_decode($historyDataString, true);
-
- if ($historyData["prev"] !== $prevVersion) {
- $logger->debug("getHistoryData: previous $prevVersion != " . $historyData["prev"], ["app" => self::$appName]);
-
- $view->unlink($historyPath);
- $logger->debug("getHistoryData: delete $historyPath", ["app" => self::$appName]);
-
- $changesPath = $path . "/" . $versionId . self::$changesExt;
- if ($view->file_exists($changesPath)) {
- $view->unlink($changesPath);
- $logger->debug("getHistoryData: delete $changesPath", ["app" => self::$appName]);
- }
- return null;
- }
-
- return $historyData;
- } catch (\Exception $e) {
- $logger->logException($e, ["message" => "getHistoryData: $fileId $versionId", "app" => self::$appName]);
- return null;
- }
- }
-
- /**
- * Check if changes is stored
- *
- * @param string $ownerId - file owner id
- * @param string $fileId - file id
- * @param string $versionId - file version
- *
- * @return bool
- */
- public static function hasChanges($ownerId, $fileId, $versionId) {
- if ($ownerId === null || $fileId === null) {
- return false;
- }
-
- list($view, $path) = self::getView($ownerId, $fileId);
- if ($view === null) {
- return false;
- }
-
- $changesPath = $path . "/" . $versionId . self::$changesExt;
- return $view->file_exists($changesPath);
- }
-
- /**
- * Get changes file
- *
- * @param string $ownerId - file owner id
- * @param string $fileId - file id
- * @param string $versionId - file version
- *
- * @return File
- */
- public static function getChangesFile($ownerId, $fileId, $versionId) {
- if ($ownerId === null || $fileId === null) {
- return null;
- }
-
- list($view, $path) = self::getView($ownerId, $fileId);
- if ($view === null) {
- return null;
- }
-
- $changesPath = $path . "/" . $versionId . self::$changesExt;
- if (!$view->file_exists($changesPath)) {
- return null;
- }
-
- $changesInfo = $view->getFileInfo($changesPath);
- $changes = new File($view->getRoot(), $view, $changesPath, $changesInfo);
-
- \OC::$server->getLogger()->debug("getChangesFile: $fileId for $ownerId get changes $changesPath", ["app" => self::$appName]);
-
- return $changes;
- }
-
- /**
- * Save history to storage
- *
- * @param FileInfo $fileInfo - file info
- * @param array $history - file history
- * @param string $changesurl - file changes
- * @param string $prevVersion - previous version for check
- */
- public static function saveHistory($fileInfo, $history, $changes, $prevVersion) {
- $logger = \OC::$server->getLogger();
-
- if ($fileInfo === null) {
- return;
- }
-
- $owner = $fileInfo->getOwner();
- if ($owner === null) {
- return;
- }
-
- if (empty($history) || empty($changes)) {
- return;
- }
-
- if ($fileInfo->getStorage()->instanceOfStorage(SharingExternalStorage::class)) {
- return;
- }
-
- $ownerId = $owner->getUID();
- $fileId = $fileInfo->getId();
- $versionId = $fileInfo->getMtime();
-
- list($view, $path) = self::getView($ownerId, $fileId, true);
-
- try {
- $changesPath = $path . "/" . $versionId . self::$changesExt;
- $view->touch($changesPath);
- $view->file_put_contents($changesPath, $changes);
-
- $history["prev"] = $prevVersion;
- $historyPath = $path . "/" . $versionId . self::$historyExt;
- $view->touch($historyPath);
- $view->file_put_contents($historyPath, json_encode($history));
-
- $logger->debug("saveHistory: $fileId for $ownerId stored changes $changesPath history $historyPath", ["app" => self::$appName]);
- } catch (\Exception $e) {
- $logger->logException($e, ["message" => "saveHistory: save $fileId history error", "app" => self::$appName]);
- }
- }
-
- /**
- * Delete all versions of file
- *
- * @param string $ownerId - file owner id
- * @param string $fileId - file id
- */
- public static function deleteAllVersions($ownerId, $fileId = null) {
- $logger = \OC::$server->getLogger();
-
- $logger->debug("deleteAllVersions $ownerId $fileId", ["app" => self::$appName]);
-
- if ($ownerId === null) {
- return;
- }
-
- list($view, $path) = self::getView($ownerId, $fileId);
- if ($view === null) {
- return;
- }
-
- $view->unlink($path);
- }
-
- /**
- * Delete changes and history
- *
- * @param string $ownerId - file owner id
- * @param string $fileId - file id
- * @param string $versionId - file version
- */
- public static function deleteVersion($ownerId, $fileId, $versionId) {
- $logger = \OC::$server->getLogger();
-
- $logger->debug("deleteVersion $fileId ($versionId)", ["app" => self::$appName]);
-
- if ($ownerId === null) {
- return;
- }
- if ($fileId === null || empty($versionId)) {
- return;
- }
-
- list($view, $path) = self::getView($ownerId, $fileId);
- if ($view === null) {
- return null;
- }
-
- $historyPath = $path . "/" . $versionId . self::$historyExt;
- if ($view->file_exists($historyPath)) {
- $view->unlink($historyPath);
- $logger->debug("deleteVersion $historyPath", ["app" => self::$appName]);
- }
-
- $changesPath = $path . "/" . $versionId . self::$changesExt;
- if ($view->file_exists($changesPath)) {
- $view->unlink($changesPath);
- $logger->debug("deleteVersion $changesPath", ["app" => self::$appName]);
- }
- }
-
- /**
- * Clear all version history
- */
- public static function clearHistory() {
- $logger = \OC::$server->getLogger();
-
- $userDatabase = new Database();
- $userIds = $userDatabase->getUsers();
-
- $view = new View("/");
-
- foreach ($userIds as $userId) {
- $path = $userId . "/" . self::$appName;
-
- if ($view->file_exists($path)) {
- $view->unlink($path);
- }
- }
-
- $logger->debug("clear all history", ["app" => self::$appName]);
- }
-
- /**
- * Save file author
- *
- * @param FileInfo $fileInfo - file info
- * @param IUser $author - version author
- */
- public static function saveAuthor($fileInfo, $author) {
- $logger = \OC::$server->getLogger();
-
- if ($fileInfo === null || $author === null) {
- return;
- }
-
- $owner = $fileInfo->getOwner();
- if ($owner === null) {
- return;
- }
-
- if ($fileInfo->getStorage()->instanceOfStorage(SharingExternalStorage::class)) {
- return;
- }
-
- $ownerId = $owner->getUID();
- $fileId = $fileInfo->getId();
- $versionId = $fileInfo->getMtime();
-
- list($view, $path) = self::getView($ownerId, $fileId, true);
-
- try {
- $authorPath = $path . "/" . $versionId . self::$authorExt;
- $view->touch($authorPath);
-
- $authorData = [
- "id" => $author->getUID(),
- "name" => $author->getDisplayName()
- ];
- $view->file_put_contents($authorPath, json_encode($authorData));
-
- $logger->debug("saveAuthor: $fileId for $ownerId stored author $authorPath", ["app" => self::$appName]);
- } catch (\Exception $e) {
- $logger->logException($e, ["message" => "saveAuthor: save $fileId author error", "app" => self::$appName]);
- }
- }
-
- /**
- * Get version author id and name
- *
- * @param string $ownerId - file owner id
- * @param string $fileId - file id
- * @param string $versionId - file version
- *
- * @return array
- */
- public static function getAuthor($ownerId, $fileId, $versionId) {
- if ($ownerId === null || $fileId === null) {
- return null;
- }
-
- list($view, $path) = self::getView($ownerId, $fileId);
- if ($view === null) {
- return null;
- }
-
- $authorPath = $path . "/" . $versionId . self::$authorExt;
- if (!$view->file_exists($authorPath)) {
- return null;
- }
-
- $authorDataString = $view->file_get_contents($authorPath);
- $author = json_decode($authorDataString, true);
-
- \OC::$server->getLogger()->debug("getAuthor: $fileId v.$versionId for $ownerId get author $authorPath", ["app" => self::$appName]);
-
- return $author;
- }
-
- /**
- * Delete version author info
- *
- * @param string $ownerId - file owner id
- * @param string $fileId - file id
- * @param string $versionId - file version
- */
- public static function deleteAuthor($ownerId, $fileId, $versionId) {
- $logger = \OC::$server->getLogger();
-
- $logger->debug("deleteAuthor $fileId ($versionId)", ["app" => self::$appName]);
-
- if ($ownerId === null) {
- return;
- }
- if ($fileId === null || empty($versionId)) {
- return;
- }
-
- list($view, $path) = self::getView($ownerId, $fileId);
- if ($view === null) {
- return null;
- }
-
- $authorPath = $path . "/" . $versionId . self::$authorExt;
- if ($view->file_exists($authorPath)) {
- $view->unlink($authorPath);
- $logger->debug("deleteAuthor $authorPath", ["app" => self::$appName]);
- }
- }
+ /**
+ * Application name
+ *
+ * @var string
+ */
+ private static $appName = "onlyoffice";
+
+ /**
+ * Changes file extension
+ *
+ * @var string
+ */
+ private static $changesExt = ".zip";
+
+ /**
+ * History file extension
+ *
+ * @var string
+ */
+ private static $historyExt = ".json";
+
+ /**
+ * File name contain author
+ *
+ * @var string
+ */
+ private static $authorExt = "_author.json";
+
+ /**
+ * Split file path and version id
+ *
+ * @param string $pathVersion - version path
+ *
+ * @return array
+ */
+ public static function splitPathVersion($pathVersion) {
+ $pos = strrpos($pathVersion, ".v");
+ if ($pos === false) {
+ return false;
+ }
+ $filePath = substr($pathVersion, 0, $pos);
+ $versionId = substr($pathVersion, 2 + $pos - \strlen($pathVersion));
+ return [$filePath, $versionId];
+ }
+
+ /**
+ * Check if folder is not exist
+ *
+ * @param View $view - view
+ * @param string $path - folder path
+ * @param bool $createIfNotExist - create folder if not exist
+ *
+ * @return bool
+ */
+ private static function checkFolderExist($view, $path, $createIfNotExist = false) {
+ if ($view->is_dir($path)) {
+ return true;
+ }
+ if (!$createIfNotExist) {
+ return false;
+ }
+ $view->mkdir($path);
+ return true;
+ }
+
+ /**
+ * Get view and path for changes
+ *
+ * @param string $userId - user id
+ * @param string $fileId - file id
+ * @param bool $createIfNotExist - create folder if not exist
+ *
+ * @return array
+ */
+ private static function getView($userId, $fileId, $createIfNotExist = false) {
+ $view = new View("/" . $userId);
+
+ $path = self::$appName;
+ if (!self::checkFolderExist($view, $path, $createIfNotExist)) {
+ return [null, null];
+ }
+
+ if ($fileId === null) {
+ return [$view, $path];
+ }
+
+ $path = $path . "/" . $fileId;
+ if (!self::checkFolderExist($view, $path, $createIfNotExist)) {
+ return [null, null];
+ }
+
+ return [$view, $path];
+ }
+
+ /**
+ * Get changes from stored to history object
+ *
+ * @param string $ownerId - file owner id
+ * @param string $fileId - file id
+ * @param string $versionId - file version
+ * @param string $prevVersion - previous version for check
+ *
+ * @return array
+ */
+ public static function getHistoryData($ownerId, $fileId, $versionId, $prevVersion) {
+ $logger = \OC::$server->getLogger();
+
+ if ($ownerId === null || $fileId === null) {
+ return null;
+ }
+
+ list($view, $path) = self::getView($ownerId, $fileId);
+ if ($view === null) {
+ return null;
+ }
+
+ $historyPath = $path . "/" . $versionId . self::$historyExt;
+ if (!$view->file_exists($historyPath)) {
+ return null;
+ }
+
+ $historyDataString = $view->file_get_contents($historyPath);
+
+ try {
+ $historyData = json_decode($historyDataString, true);
+
+ if ($historyData["prev"] !== $prevVersion) {
+ $logger->debug("getHistoryData: previous $prevVersion != " . $historyData["prev"], ["app" => self::$appName]);
+
+ $view->unlink($historyPath);
+ $logger->debug("getHistoryData: delete $historyPath", ["app" => self::$appName]);
+
+ $changesPath = $path . "/" . $versionId . self::$changesExt;
+ if ($view->file_exists($changesPath)) {
+ $view->unlink($changesPath);
+ $logger->debug("getHistoryData: delete $changesPath", ["app" => self::$appName]);
+ }
+ return null;
+ }
+
+ return $historyData;
+ } catch (\Exception $e) {
+ $logger->logException($e, ["message" => "getHistoryData: $fileId $versionId", "app" => self::$appName]);
+ return null;
+ }
+ }
+
+ /**
+ * Check if changes is stored
+ *
+ * @param string $ownerId - file owner id
+ * @param string $fileId - file id
+ * @param string $versionId - file version
+ *
+ * @return bool
+ */
+ public static function hasChanges($ownerId, $fileId, $versionId) {
+ if ($ownerId === null || $fileId === null) {
+ return false;
+ }
+
+ list($view, $path) = self::getView($ownerId, $fileId);
+ if ($view === null) {
+ return false;
+ }
+
+ $changesPath = $path . "/" . $versionId . self::$changesExt;
+ return $view->file_exists($changesPath);
+ }
+
+ /**
+ * Get changes file
+ *
+ * @param string $ownerId - file owner id
+ * @param string $fileId - file id
+ * @param string $versionId - file version
+ *
+ * @return File
+ */
+ public static function getChangesFile($ownerId, $fileId, $versionId) {
+ if ($ownerId === null || $fileId === null) {
+ return null;
+ }
+
+ list($view, $path) = self::getView($ownerId, $fileId);
+ if ($view === null) {
+ return null;
+ }
+
+ $changesPath = $path . "/" . $versionId . self::$changesExt;
+ if (!$view->file_exists($changesPath)) {
+ return null;
+ }
+
+ $changesInfo = $view->getFileInfo($changesPath);
+ $changes = new File($view->getRoot(), $view, $changesPath, $changesInfo);
+
+ \OC::$server->getLogger()->debug("getChangesFile: $fileId for $ownerId get changes $changesPath", ["app" => self::$appName]);
+
+ return $changes;
+ }
+
+ /**
+ * Save history to storage
+ *
+ * @param FileInfo $fileInfo - file info
+ * @param array $history - file history
+ * @param string $changesurl - file changes
+ * @param string $prevVersion - previous version for check
+ */
+ public static function saveHistory($fileInfo, $history, $changes, $prevVersion) {
+ $logger = \OC::$server->getLogger();
+
+ if ($fileInfo === null) {
+ return;
+ }
+
+ $owner = $fileInfo->getOwner();
+ if ($owner === null) {
+ return;
+ }
+
+ if (empty($history) || empty($changes)) {
+ return;
+ }
+
+ if ($fileInfo->getStorage()->instanceOfStorage(SharingExternalStorage::class)) {
+ return;
+ }
+
+ $ownerId = $owner->getUID();
+ $fileId = $fileInfo->getId();
+ $versionId = $fileInfo->getMtime();
+
+ list($view, $path) = self::getView($ownerId, $fileId, true);
+
+ try {
+ $changesPath = $path . "/" . $versionId . self::$changesExt;
+ $view->touch($changesPath);
+ $view->file_put_contents($changesPath, $changes);
+
+ $history["prev"] = $prevVersion;
+ $historyPath = $path . "/" . $versionId . self::$historyExt;
+ $view->touch($historyPath);
+ $view->file_put_contents($historyPath, json_encode($history));
+
+ $logger->debug("saveHistory: $fileId for $ownerId stored changes $changesPath history $historyPath", ["app" => self::$appName]);
+ } catch (\Exception $e) {
+ $logger->logException($e, ["message" => "saveHistory: save $fileId history error", "app" => self::$appName]);
+ }
+ }
+
+ /**
+ * Delete all versions of file
+ *
+ * @param string $ownerId - file owner id
+ * @param string $fileId - file id
+ */
+ public static function deleteAllVersions($ownerId, $fileId = null) {
+ $logger = \OC::$server->getLogger();
+
+ $logger->debug("deleteAllVersions $ownerId $fileId", ["app" => self::$appName]);
+
+ if ($ownerId === null) {
+ return;
+ }
+
+ list($view, $path) = self::getView($ownerId, $fileId);
+ if ($view === null) {
+ return;
+ }
+
+ $view->unlink($path);
+ }
+
+ /**
+ * Delete changes and history
+ *
+ * @param string $ownerId - file owner id
+ * @param string $fileId - file id
+ * @param string $versionId - file version
+ */
+ public static function deleteVersion($ownerId, $fileId, $versionId) {
+ $logger = \OC::$server->getLogger();
+
+ $logger->debug("deleteVersion $fileId ($versionId)", ["app" => self::$appName]);
+
+ if ($ownerId === null) {
+ return;
+ }
+ if ($fileId === null || empty($versionId)) {
+ return;
+ }
+
+ list($view, $path) = self::getView($ownerId, $fileId);
+ if ($view === null) {
+ return null;
+ }
+
+ $historyPath = $path . "/" . $versionId . self::$historyExt;
+ if ($view->file_exists($historyPath)) {
+ $view->unlink($historyPath);
+ $logger->debug("deleteVersion $historyPath", ["app" => self::$appName]);
+ }
+
+ $changesPath = $path . "/" . $versionId . self::$changesExt;
+ if ($view->file_exists($changesPath)) {
+ $view->unlink($changesPath);
+ $logger->debug("deleteVersion $changesPath", ["app" => self::$appName]);
+ }
+ }
+
+ /**
+ * Clear all version history
+ */
+ public static function clearHistory() {
+ $logger = \OC::$server->getLogger();
+
+ $userDatabase = new Database();
+ $userIds = $userDatabase->getUsers();
+
+ $view = new View("/");
+
+ foreach ($userIds as $userId) {
+ $path = $userId . "/" . self::$appName;
+
+ if ($view->file_exists($path)) {
+ $view->unlink($path);
+ }
+ }
+
+ $logger->debug("clear all history", ["app" => self::$appName]);
+ }
+
+ /**
+ * Save file author
+ *
+ * @param FileInfo $fileInfo - file info
+ * @param IUser $author - version author
+ */
+ public static function saveAuthor($fileInfo, $author) {
+ $logger = \OC::$server->getLogger();
+
+ if ($fileInfo === null || $author === null) {
+ return;
+ }
+
+ $owner = $fileInfo->getOwner();
+ if ($owner === null) {
+ return;
+ }
+
+ if ($fileInfo->getStorage()->instanceOfStorage(SharingExternalStorage::class)) {
+ return;
+ }
+
+ $ownerId = $owner->getUID();
+ $fileId = $fileInfo->getId();
+ $versionId = $fileInfo->getMtime();
+
+ list($view, $path) = self::getView($ownerId, $fileId, true);
+
+ try {
+ $authorPath = $path . "/" . $versionId . self::$authorExt;
+ $view->touch($authorPath);
+
+ $authorData = [
+ "id" => $author->getUID(),
+ "name" => $author->getDisplayName()
+ ];
+ $view->file_put_contents($authorPath, json_encode($authorData));
+
+ $logger->debug("saveAuthor: $fileId for $ownerId stored author $authorPath", ["app" => self::$appName]);
+ } catch (\Exception $e) {
+ $logger->logException($e, ["message" => "saveAuthor: save $fileId author error", "app" => self::$appName]);
+ }
+ }
+
+ /**
+ * Get version author id and name
+ *
+ * @param string $ownerId - file owner id
+ * @param string $fileId - file id
+ * @param string $versionId - file version
+ *
+ * @return array
+ */
+ public static function getAuthor($ownerId, $fileId, $versionId) {
+ if ($ownerId === null || $fileId === null) {
+ return null;
+ }
+
+ list($view, $path) = self::getView($ownerId, $fileId);
+ if ($view === null) {
+ return null;
+ }
+
+ $authorPath = $path . "/" . $versionId . self::$authorExt;
+ if (!$view->file_exists($authorPath)) {
+ return null;
+ }
+
+ $authorDataString = $view->file_get_contents($authorPath);
+ $author = json_decode($authorDataString, true);
+
+ \OC::$server->getLogger()->debug("getAuthor: $fileId v.$versionId for $ownerId get author $authorPath", ["app" => self::$appName]);
+
+ return $author;
+ }
+
+ /**
+ * Delete version author info
+ *
+ * @param string $ownerId - file owner id
+ * @param string $fileId - file id
+ * @param string $versionId - file version
+ */
+ public static function deleteAuthor($ownerId, $fileId, $versionId) {
+ $logger = \OC::$server->getLogger();
+
+ $logger->debug("deleteAuthor $fileId ($versionId)", ["app" => self::$appName]);
+
+ if ($ownerId === null) {
+ return;
+ }
+ if ($fileId === null || empty($versionId)) {
+ return;
+ }
+
+ list($view, $path) = self::getView($ownerId, $fileId);
+ if ($view === null) {
+ return null;
+ }
+
+ $authorPath = $path . "/" . $versionId . self::$authorExt;
+ if ($view->file_exists($authorPath)) {
+ $view->unlink($authorPath);
+ $logger->debug("deleteAuthor $authorPath", ["app" => self::$appName]);
+ }
+ }
}
diff --git a/lib/hookhandler.php b/lib/hookhandler.php
index fe74c171..5d7973ca 100644
--- a/lib/hookhandler.php
+++ b/lib/hookhandler.php
@@ -31,20 +31,20 @@
* @package OCA\Onlyoffice
*/
class HookHandler {
- public static function PublicPage() {
- $appName = "onlyoffice";
+ public static function PublicPage() {
+ $appName = "onlyoffice";
- $appConfig = new AppConfig($appName);
+ $appConfig = new AppConfig($appName);
- if (!empty($appConfig->GetDocumentServerUrl()) && $appConfig->SettingsAreSuccessful()) {
- Util::addScript("onlyoffice", "main");
- Util::addScript("onlyoffice", "share");
+ if (!empty($appConfig->GetDocumentServerUrl()) && $appConfig->SettingsAreSuccessful()) {
+ Util::addScript("onlyoffice", "main");
+ Util::addScript("onlyoffice", "share");
- if ($appConfig->GetSameTab()) {
- Util::addScript("onlyoffice", "listener");
- }
+ if ($appConfig->GetSameTab()) {
+ Util::addScript("onlyoffice", "listener");
+ }
- Util::addStyle("onlyoffice", "main");
- }
- }
+ Util::addStyle("onlyoffice", "main");
+ }
+ }
}
diff --git a/lib/hooks.php b/lib/hooks.php
index 87632d2f..2b464f00 100644
--- a/lib/hooks.php
+++ b/lib/hooks.php
@@ -32,154 +32,154 @@
* @package OCA\Onlyoffice
*/
class Hooks {
- /**
- * Application name
- *
- * @var string
- */
- private static $appName = "onlyoffice";
-
- public static function connectHooks() {
- // Listen user deletion
- Util::connectHook("OC_User", "pre_deleteUser", Hooks::class, "userDelete");
-
- // Listen file change
- Util::connectHook("OC_Filesystem", "write", Hooks::class, "fileUpdate");
-
- // Listen file deletion
- Util::connectHook("OC_Filesystem", "delete", Hooks::class, "fileDelete");
-
- // Listen file version deletion
- Util::connectHook("\OCP\Versions", "preDelete", Hooks::class, "fileVersionDelete");
-
- // Listen file version restore
- Util::connectHook("\OCP\Versions", "rollback", Hooks::class, "fileVersionRestore");
- }
-
- /**
- * Erase user file versions
- *
- * @param array $params - hook params
- */
- public static function userDelete($params) {
- $userId = $params["uid"];
-
- FileVersions::deleteAllVersions($userId);
- }
-
- /**
- * Listen of file change
- *
- * @param array $params - hook params
- */
- public static function fileUpdate($params) {
- $filePath = $params[Filesystem::signal_param_path];
- if (empty($filePath)) {
- return;
- }
-
- $fileInfo = Filesystem::getFileInfo($filePath);
- if ($fileInfo === false) {
- return;
- }
-
- $fileId = $fileInfo->getId();
-
- KeyManager::delete($fileId);
-
- \OC::$server->getLogger()->debug("Hook fileUpdate " . json_encode($params), ["app" => self::$appName]);
- }
-
- /**
- * Erase versions of deleted file
- *
- * @param array $params - hook params
- */
- public static function fileDelete($params) {
- $filePath = $params[Filesystem::signal_param_path];
- if (empty($filePath)) {
- return;
- }
-
- try {
- $ownerId = Filesystem::getOwner($filePath);
-
- $fileInfo = Filesystem::getFileInfo($filePath);
- if ($fileInfo === false) {
- return;
- }
-
- $fileId = $fileInfo->getId();
-
- KeyManager::delete($fileId, true);
-
- FileVersions::deleteAllVersions($ownerId, $fileId);
- } catch (\Exception $e) {
- \OC::$server->getLogger()->logException($e, ["message" => "Hook: fileDelete " . json_encode($params), "app" => self::$appName]);
- }
- }
-
- /**
- * Erase versions of deleted version of file
- *
- * @param array $params - hook param
- */
- public static function fileVersionDelete($params) {
- $pathVersion = $params["path"];
- if (empty($pathVersion)) {
- return;
- }
-
- try {
- list($filePath, $versionId) = FileVersions::splitPathVersion($pathVersion);
- if (empty($filePath)) {
- return;
- }
-
- $ownerId = Filesystem::getOwner($filePath);
-
- $fileInfo = Filesystem::getFileInfo($filePath);
- if ($fileInfo === false) {
- return;
- }
-
- $fileId = $fileInfo->getId();
-
- FileVersions::deleteVersion($ownerId, $fileId, $versionId);
- FileVersions::deleteAuthor($ownerId, $fileId, $versionId);
- } catch (\Exception $e) {
- \OC::$server->getLogger()->logException($e, ["message" => "Hook: fileVersionDelete " . json_encode($params), "app" => self::$appName]);
- }
- }
-
- /**
- * Erase versions of restored version of file
- *
- * @param array $params - hook param
- */
- public static function fileVersionRestore($params) {
- $filePath = $params["path"];
- if (empty($filePath)) {
- return;
- }
-
- $versionId = $params["revision"];
-
- try {
- $ownerId = Filesystem::getOwner($filePath);
-
- $fileInfo = Filesystem::getFileInfo($filePath);
- if ($fileInfo === false) {
- return;
- }
-
- $fileId = $fileInfo->getId();
-
- KeyManager::delete($fileId);
-
- FileVersions::deleteVersion($ownerId, $fileId, $versionId);
- } catch (\Exception $e) {
- \OC::$server->getLogger()->logException($e, ["message" => "Hook: fileVersionRestore " . json_encode($params), "app" => self::$appName]);
- }
- }
+ /**
+ * Application name
+ *
+ * @var string
+ */
+ private static $appName = "onlyoffice";
+
+ public static function connectHooks() {
+ // Listen user deletion
+ Util::connectHook("OC_User", "pre_deleteUser", Hooks::class, "userDelete");
+
+ // Listen file change
+ Util::connectHook("OC_Filesystem", "write", Hooks::class, "fileUpdate");
+
+ // Listen file deletion
+ Util::connectHook("OC_Filesystem", "delete", Hooks::class, "fileDelete");
+
+ // Listen file version deletion
+ Util::connectHook("\OCP\Versions", "preDelete", Hooks::class, "fileVersionDelete");
+
+ // Listen file version restore
+ Util::connectHook("\OCP\Versions", "rollback", Hooks::class, "fileVersionRestore");
+ }
+
+ /**
+ * Erase user file versions
+ *
+ * @param array $params - hook params
+ */
+ public static function userDelete($params) {
+ $userId = $params["uid"];
+
+ FileVersions::deleteAllVersions($userId);
+ }
+
+ /**
+ * Listen of file change
+ *
+ * @param array $params - hook params
+ */
+ public static function fileUpdate($params) {
+ $filePath = $params[Filesystem::signal_param_path];
+ if (empty($filePath)) {
+ return;
+ }
+
+ $fileInfo = Filesystem::getFileInfo($filePath);
+ if ($fileInfo === false) {
+ return;
+ }
+
+ $fileId = $fileInfo->getId();
+
+ KeyManager::delete($fileId);
+
+ \OC::$server->getLogger()->debug("Hook fileUpdate " . json_encode($params), ["app" => self::$appName]);
+ }
+
+ /**
+ * Erase versions of deleted file
+ *
+ * @param array $params - hook params
+ */
+ public static function fileDelete($params) {
+ $filePath = $params[Filesystem::signal_param_path];
+ if (empty($filePath)) {
+ return;
+ }
+
+ try {
+ $ownerId = Filesystem::getOwner($filePath);
+
+ $fileInfo = Filesystem::getFileInfo($filePath);
+ if ($fileInfo === false) {
+ return;
+ }
+
+ $fileId = $fileInfo->getId();
+
+ KeyManager::delete($fileId, true);
+
+ FileVersions::deleteAllVersions($ownerId, $fileId);
+ } catch (\Exception $e) {
+ \OC::$server->getLogger()->logException($e, ["message" => "Hook: fileDelete " . json_encode($params), "app" => self::$appName]);
+ }
+ }
+
+ /**
+ * Erase versions of deleted version of file
+ *
+ * @param array $params - hook param
+ */
+ public static function fileVersionDelete($params) {
+ $pathVersion = $params["path"];
+ if (empty($pathVersion)) {
+ return;
+ }
+
+ try {
+ list($filePath, $versionId) = FileVersions::splitPathVersion($pathVersion);
+ if (empty($filePath)) {
+ return;
+ }
+
+ $ownerId = Filesystem::getOwner($filePath);
+
+ $fileInfo = Filesystem::getFileInfo($filePath);
+ if ($fileInfo === false) {
+ return;
+ }
+
+ $fileId = $fileInfo->getId();
+
+ FileVersions::deleteVersion($ownerId, $fileId, $versionId);
+ FileVersions::deleteAuthor($ownerId, $fileId, $versionId);
+ } catch (\Exception $e) {
+ \OC::$server->getLogger()->logException($e, ["message" => "Hook: fileVersionDelete " . json_encode($params), "app" => self::$appName]);
+ }
+ }
+
+ /**
+ * Erase versions of restored version of file
+ *
+ * @param array $params - hook param
+ */
+ public static function fileVersionRestore($params) {
+ $filePath = $params["path"];
+ if (empty($filePath)) {
+ return;
+ }
+
+ $versionId = $params["revision"];
+
+ try {
+ $ownerId = Filesystem::getOwner($filePath);
+
+ $fileInfo = Filesystem::getFileInfo($filePath);
+ if ($fileInfo === false) {
+ return;
+ }
+
+ $fileId = $fileInfo->getId();
+
+ KeyManager::delete($fileId);
+
+ FileVersions::deleteVersion($ownerId, $fileId, $versionId);
+ } catch (\Exception $e) {
+ \OC::$server->getLogger()->logException($e, ["message" => "Hook: fileVersionRestore " . json_encode($params), "app" => self::$appName]);
+ }
+ }
}
diff --git a/lib/keymanager.php b/lib/keymanager.php
index 1ab475c9..4cf4a0fa 100644
--- a/lib/keymanager.php
+++ b/lib/keymanager.php
@@ -25,125 +25,125 @@
* @package OCA\Onlyoffice
*/
class KeyManager {
- /**
- * Table name
- */
- private const TableName_Key = "onlyoffice_filekey";
+ /**
+ * Table name
+ */
+ private const TableName_Key = "onlyoffice_filekey";
- /**
- * Get document identifier
- *
- * @param integer $fileId - file identifier
- *
- * @return string
- */
- public static function get($fileId) {
- $connection = \OC::$server->getDatabaseConnection();
- $select = $connection->prepare("
+ /**
+ * Get document identifier
+ *
+ * @param integer $fileId - file identifier
+ *
+ * @return string
+ */
+ public static function get($fileId) {
+ $connection = \OC::$server->getDatabaseConnection();
+ $select = $connection->prepare("
SELECT `key`
FROM `*PREFIX*" . self::TableName_Key . "`
WHERE `file_id` = ?
");
- $result = $select->execute([$fileId]);
+ $result = $select->execute([$fileId]);
- $keys = $result ? $select->fetch() : [];
- $key = \is_array($keys) && isset($keys["key"]) ? $keys["key"] : "";
+ $keys = $result ? $select->fetch() : [];
+ $key = \is_array($keys) && isset($keys["key"]) ? $keys["key"] : "";
- return $key;
- }
+ return $key;
+ }
- /**
- * Store document identifier
- *
- * @param integer $fileId - file identifier
- * @param integer $key - file key
- *
- * @return bool
- */
- public static function set($fileId, $key) {
- $connection = \OC::$server->getDatabaseConnection();
- $insert = $connection->prepare("
+ /**
+ * Store document identifier
+ *
+ * @param integer $fileId - file identifier
+ * @param integer $key - file key
+ *
+ * @return bool
+ */
+ public static function set($fileId, $key) {
+ $connection = \OC::$server->getDatabaseConnection();
+ $insert = $connection->prepare("
INSERT INTO `*PREFIX*" . self::TableName_Key . "`
(`file_id`, `key`)
VALUES (?, ?)
");
- return (bool)$insert->execute([$fileId, $key]);
- }
+ return (bool)$insert->execute([$fileId, $key]);
+ }
- /**
- * Delete document identifier
- *
- * @param integer $fileId - file identifier
- * @param bool $unlock - delete even with lock label
- *
- * @return bool
- */
- public static function delete($fileId, $unlock = false) {
- $connection = \OC::$server->getDatabaseConnection();
- $delete = $connection->prepare(
- "
+ /**
+ * Delete document identifier
+ *
+ * @param integer $fileId - file identifier
+ * @param bool $unlock - delete even with lock label
+ *
+ * @return bool
+ */
+ public static function delete($fileId, $unlock = false) {
+ $connection = \OC::$server->getDatabaseConnection();
+ $delete = $connection->prepare(
+ "
DELETE FROM `*PREFIX*" . self::TableName_Key . "`
WHERE `file_id` = ?
" . ($unlock === false ? "AND `lock` != 1" : "")
- );
- return (bool)$delete->execute([$fileId]);
- }
+ );
+ return (bool)$delete->execute([$fileId]);
+ }
- /**
- * Change lock status
- *
- * @param integer $fileId - file identifier
- * @param bool $lock - status
- *
- * @return bool
- */
- public static function lock($fileId, $lock = true) {
- $connection = \OC::$server->getDatabaseConnection();
- $update = $connection->prepare("
+ /**
+ * Change lock status
+ *
+ * @param integer $fileId - file identifier
+ * @param bool $lock - status
+ *
+ * @return bool
+ */
+ public static function lock($fileId, $lock = true) {
+ $connection = \OC::$server->getDatabaseConnection();
+ $update = $connection->prepare("
UPDATE `*PREFIX*" . self::TableName_Key . "`
SET `lock` = ?
WHERE `file_id` = ?
");
- return (bool)$update->execute([$lock === true ? 1 : 0, $fileId]);
- }
+ return (bool)$update->execute([$lock === true ? 1 : 0, $fileId]);
+ }
- /**
- * Change forcesave status
- *
- * @param integer $fileId - file identifier
- * @param bool $fs - status
- *
- * @return bool
- */
- public static function setForcesave($fileId, $fs = true) {
- $connection = \OC::$server->getDatabaseConnection();
- $update = $connection->prepare("
+ /**
+ * Change forcesave status
+ *
+ * @param integer $fileId - file identifier
+ * @param bool $fs - status
+ *
+ * @return bool
+ */
+ public static function setForcesave($fileId, $fs = true) {
+ $connection = \OC::$server->getDatabaseConnection();
+ $update = $connection->prepare("
UPDATE `*PREFIX*" . self::TableName_Key . "`
SET `fs` = ?
WHERE `file_id` = ?
");
- return (bool)$update->execute([$fs === true ? 1 : 0, $fileId]);
- }
+ return (bool)$update->execute([$fs === true ? 1 : 0, $fileId]);
+ }
- /**
- * Get forcesave status
- *
- * @param integer $fileId - file identifier
- *
- * @return bool
- */
- public static function wasForcesave($fileId) {
- $connection = \OC::$server->getDatabaseConnection();
- $select = $connection->prepare("
+ /**
+ * Get forcesave status
+ *
+ * @param integer $fileId - file identifier
+ *
+ * @return bool
+ */
+ public static function wasForcesave($fileId) {
+ $connection = \OC::$server->getDatabaseConnection();
+ $select = $connection->prepare("
SELECT `fs`
FROM `*PREFIX*" . self::TableName_Key . "`
WHERE `file_id` = ?
");
- $result = $select->execute([$fileId]);
+ $result = $select->execute([$fileId]);
- $rows = $result ? $select->fetch() : [];
- $fs = \is_array($rows) && isset($rows["fs"]) ? $rows["fs"] : "";
+ $rows = $result ? $select->fetch() : [];
+ $fs = \is_array($rows) && isset($rows["fs"]) ? $rows["fs"] : "";
- return $fs === "1";
- }
+ return $fs === "1";
+ }
}
diff --git a/lib/notifier.php b/lib/notifier.php
index 689a5b8d..ecdf1bbd 100644
--- a/lib/notifier.php
+++ b/lib/notifier.php
@@ -27,110 +27,110 @@
use OCP\Notification\INotifier;
class Notifier implements INotifier {
- /**
- * Application name
- *
- * @var string
- */
- private $appName;
-
- /**
- * IFactory
- *
- * @var IFactory
- */
- private $l10nFactory;
-
- /**
- * Url generator service
- *
- * @var IURLGenerator
- */
- private $urlGenerator;
-
- /**
- * Logger
- *
- * @var ILogger
- */
- private $logger;
-
- /**
- * User manager
- *
- * @var IUserManager
- */
- private $userManager;
-
- /**
- * @param string $AppName - application name
- * @param IFactory $l10NFactory - l10n
- * @param IURLGenerator $urlGenerator - url generator service
- * @param ILogger $logger - logger
- * @param IUserManager $userManager - user manager
- */
- public function __construct(
- string $appName,
- IFactory $l10nFactory,
- IURLGenerator $urlGenerator,
- ILogger $logger,
- IUserManager $userManager
- ) {
- $this->appName = $appName;
- $this->l10nFactory = $l10nFactory;
- $this->urlGenerator = $urlGenerator;
- $this->logger = $logger;
- $this->userManager = $userManager;
- }
-
- /**
- * @param INotification $notification - notification object
- * @param string $languageCode - the code of the language that should be used to prepare the notification
- *
- * @return INotification
- */
- public function prepare($notification, $languageCode) {
- if ($notification->getApp() !== $this->appName) {
- throw new \InvalidArgumentException("Notification not from " . $this->appName);
- }
-
- $parameters = $notification->getSubjectParameters();
- $trans = $this->l10nFactory->get($this->appName, $languageCode);
-
- switch ($notification->getObjectType()) {
- case "editorsCheck":
- $message = $trans->t("Please check the settings to resolve the problem.");
- $appSettingsLink = $this->urlGenerator->getAbsoluteURL("/settings/admin?sectionid=additional");
- $notification->setLink($appSettingsLink);
- $notification->setParsedSubject($notification->getObjectId())
- ->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath($this->appName, 'app-dark.svg')));
- $notification->setParsedMessage($message);
- break;
- case "mention":
- $notifierId = $parameters["notifierId"];
- $fileId = $parameters["fileId"];
- $fileName = $parameters["fileName"];
- $anchor = $parameters["anchor"];
-
- $this->logger->info("Notify prepare: from $notifierId about $fileId ", ["app" => $this->appName]);
-
- $notifier = $this->userManager->get($notifierId);
- $notifierName = $notifier->getDisplayName();
- $trans = $this->l10nFactory->get($this->appName, $languageCode);
-
- $notification->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath($this->appName, "app-dark.svg")));
- $notification->setParsedSubject($trans->t("%1\$s mentioned in the %2\$s: \"%3\$s\".", [$notifierName, $fileName, $notification->getObjectId()]));
-
- $editorLink = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".editor.index", [
- "fileId" => $fileId,
- "anchor" => $anchor
- ]);
-
- $notification->setLink($editorLink);
- break;
- default:
- $this->logger->info("Unsupported notification object: ".$notification->getObjectType(), ["app" => $this->appName]);
- }
- return $notification;
- }
+ /**
+ * Application name
+ *
+ * @var string
+ */
+ private $appName;
+
+ /**
+ * IFactory
+ *
+ * @var IFactory
+ */
+ private $l10nFactory;
+
+ /**
+ * Url generator service
+ *
+ * @var IURLGenerator
+ */
+ private $urlGenerator;
+
+ /**
+ * Logger
+ *
+ * @var ILogger
+ */
+ private $logger;
+
+ /**
+ * User manager
+ *
+ * @var IUserManager
+ */
+ private $userManager;
+
+ /**
+ * @param string $AppName - application name
+ * @param IFactory $l10NFactory - l10n
+ * @param IURLGenerator $urlGenerator - url generator service
+ * @param ILogger $logger - logger
+ * @param IUserManager $userManager - user manager
+ */
+ public function __construct(
+ string $appName,
+ IFactory $l10nFactory,
+ IURLGenerator $urlGenerator,
+ ILogger $logger,
+ IUserManager $userManager
+ ) {
+ $this->appName = $appName;
+ $this->l10nFactory = $l10nFactory;
+ $this->urlGenerator = $urlGenerator;
+ $this->logger = $logger;
+ $this->userManager = $userManager;
+ }
+
+ /**
+ * @param INotification $notification - notification object
+ * @param string $languageCode - the code of the language that should be used to prepare the notification
+ *
+ * @return INotification
+ */
+ public function prepare($notification, $languageCode) {
+ if ($notification->getApp() !== $this->appName) {
+ throw new \InvalidArgumentException("Notification not from " . $this->appName);
+ }
+
+ $parameters = $notification->getSubjectParameters();
+ $trans = $this->l10nFactory->get($this->appName, $languageCode);
+
+ switch ($notification->getObjectType()) {
+ case "editorsCheck":
+ $message = $trans->t("Please check the settings to resolve the problem.");
+ $appSettingsLink = $this->urlGenerator->getAbsoluteURL("/settings/admin?sectionid=additional");
+ $notification->setLink($appSettingsLink);
+ $notification->setParsedSubject($notification->getObjectId())
+ ->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath($this->appName, 'app-dark.svg')));
+ $notification->setParsedMessage($message);
+ break;
+ case "mention":
+ $notifierId = $parameters["notifierId"];
+ $fileId = $parameters["fileId"];
+ $fileName = $parameters["fileName"];
+ $anchor = $parameters["anchor"];
+
+ $this->logger->info("Notify prepare: from $notifierId about $fileId ", ["app" => $this->appName]);
+
+ $notifier = $this->userManager->get($notifierId);
+ $notifierName = $notifier->getDisplayName();
+ $trans = $this->l10nFactory->get($this->appName, $languageCode);
+
+ $notification->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath($this->appName, "app-dark.svg")));
+ $notification->setParsedSubject($trans->t("%1\$s mentioned in the %2\$s: \"%3\$s\".", [$notifierName, $fileName, $notification->getObjectId()]));
+
+ $editorLink = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".editor.index", [
+ "fileId" => $fileId,
+ "anchor" => $anchor
+ ]);
+
+ $notification->setLink($editorLink);
+ break;
+ default:
+ $this->logger->info("Unsupported notification object: ".$notification->getObjectType(), ["app" => $this->appName]);
+ }
+ return $notification;
+ }
}
diff --git a/lib/preview.php b/lib/preview.php
index 86e7444f..585a61b6 100644
--- a/lib/preview.php
+++ b/lib/preview.php
@@ -45,349 +45,349 @@
* @package OCA\Onlyoffice
*/
class Preview implements IProvider2 {
- /**
- * Application name
- *
- * @var string
- */
- private $appName;
-
- /**
- * Root folder
- *
- * @var IRootFolder
- */
- private $root;
-
- /**
- * User manager
- *
- * @var IUserManager
- */
- private $userManager;
-
- /**
- * Logger
- *
- * @var ILogger
- */
- private $logger;
-
- /**
- * l10n service
- *
- * @var IL10N
- */
- private $trans;
-
- /**
- * Application configuration
- *
- * @var AppConfig
- */
- private $config;
-
- /**
- * Url generator service
- *
- * @var IURLGenerator
- */
- private $urlGenerator;
-
- /**
- * Hash generator
- *
- * @var Crypt
- */
- private $crypt;
-
- /**
- * File version manager
- *
- * @var VersionManager
- */
- private $versionManager;
-
- /**
- * File utility
- *
- * @var FileUtility
- */
- private $fileUtility;
-
- /**
- * Capabilities mimetype
- *
- * @var Array
- */
- public static $capabilities = [
- "text/csv",
- "application/msword",
- "application/vnd.ms-word.document.macroEnabled.12",
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf",
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform",
- "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
- "application/epub+zip",
- "text/html",
- "application/vnd.oasis.opendocument.presentation",
- "application/vnd.oasis.opendocument.spreadsheet",
- "application/vnd.oasis.opendocument.text",
- "application/vnd.oasis.opendocument.presentation-template",
- "application/vnd.oasis.opendocument.spreadsheet-template",
- "application/vnd.oasis.opendocument.text-template",
- "application/pdf",
- "application/vnd.ms-powerpoint.template.macroEnabled.12",
- "application/vnd.openxmlformats-officedocument.presentationml.template",
- "application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
- "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
- "application/vnd.ms-powerpoint",
- "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
- "application/vnd.openxmlformats-officedocument.presentationml.presentation",
- "text/rtf",
- "text/plain",
- "application/vnd.ms-excel",
- "application/vnd.ms-excel.sheet.macroEnabled.12",
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
- "application/vnd.ms-excel.template.macroEnabled.12",
- "application/vnd.openxmlformats-officedocument.spreadsheetml.template"
- ];
-
- /**
- * Converted thumbnail format
- */
- private const thumbExtension = "jpeg";
-
- /**
- * @param string $appName - application name
- * @param IRootFolder $root - root folder
- * @param ILogger $logger - logger
- * @param IL10N $trans - l10n service
- * @param AppConfig $config - application configuration
- * @param IURLGenerator $urlGenerator - url generator service
- * @param Crypt $crypt - hash generator
- * @param IManager $shareManager - share manager
- * @param ISession $session - session
- * @param IUserManager $userManager - user manager
- */
- public function __construct(
- string $appName,
- IRootFolder $root,
- ILogger $logger,
- IL10N $trans,
- AppConfig $config,
- IURLGenerator $urlGenerator,
- Crypt $crypt,
- IManager $shareManager,
- ISession $session,
- IUserManager $userManager
- ) {
- $this->appName = $appName;
- $this->root = $root;
- $this->logger = $logger;
- $this->trans = $trans;
- $this->config = $config;
- $this->urlGenerator = $urlGenerator;
- $this->crypt = $crypt;
- $this->userManager = $userManager;
-
- $this->versionManager = new VersionManager($appName, $root);
-
- $this->fileUtility = new FileUtility($appName, $trans, $logger, $config, $shareManager, $session);
- }
-
- /**
- * Return mime type
- */
- public static function getMimeTypeRegex() {
- $mimeTypeRegex = "";
- foreach (self::$capabilities as $format) {
- if (!empty($mimeTypeRegex)) {
- $mimeTypeRegex = $mimeTypeRegex . "|";
- }
- $mimeTypeRegex = $mimeTypeRegex . str_replace("/", "\/", $format);
- }
- $mimeTypeRegex = "/" . $mimeTypeRegex . "/";
-
- return $mimeTypeRegex;
- }
-
- /**
- * Return mime type
- */
- public function getMimeType() {
- $m = self::getMimeTypeRegex();
- return $m;
- }
-
- /**
- * The method checks if the file can be converted
- *
- * @param FileInfo $fileInfo - File
- *
- * @return bool
- */
- public function isAvailable(FileInfo $fileInfo) {
- if ($this->config->GetPreview() !== true) {
- return false;
- }
- if (!$fileInfo
- || $fileInfo->getSize() === 0
- || $fileInfo->getSize() > $this->config->GetLimitThumbSize()) {
- return false;
- }
- if (!\in_array($fileInfo->getMimetype(), self::$capabilities, true)) {
- return false;
- }
- return true;
- }
-
- /**
- * The method is generated thumbnail for file and returned image object
- *
- * @param File $file - file
- * @param int $maxX - The maximum X size of the thumbnail
- * @param int $maxY - The maximum Y size of the thumbnail
- * @param bool $scalingup - Disable/Enable upscaling of previews
- *
- * @return Image|bool false if no preview was generated
- */
- public function getThumbnail($file, $maxX, $maxY, $scalingup) {
- if (empty($file)) {
- $this->logger->error("getThumbnail is impossible. File is null", ["app" => $this->appName]);
- return false;
- }
-
- $this->logger->debug("getThumbnail " . $file->getPath() . " $maxX $maxY", ["app" => $this->appName]);
-
- list($fileUrl, $extension, $key) = $this->getFileParam($file);
- if ($fileUrl === null || $extension === null || $key === null) {
- return false;
- }
-
- $imageUrl = null;
- $documentService = new DocumentService($this->trans, $this->config);
- try {
- $imageUrl = $documentService->GetConvertedUri($fileUrl, $extension, self::thumbExtension, $key);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "GetConvertedUri: from $extension to " . self::thumbExtension, "app" => $this->appName]);
- return false;
- }
-
- try {
- $thumbnail = $documentService->Request($imageUrl);
- } catch (\Exception $e) {
- $this->logger->logException($e, ["message" => "Failed to download thumbnail", "app" => $this->appName]);
- return false;
- }
-
- $image = new Image();
- $image->loadFromData($thumbnail);
-
- if ($image->valid()) {
- $image->scaleDownToFit($maxX, $maxY);
- return $image;
- }
-
- return false;
- }
-
- /**
- * Generate secure link to download document
- *
- * @param File $file - file
- * @param IUser $user - user with access
- * @param int $version - file version
- *
- * @return string
- */
- private function getUrl($file, $user = null, $version = 0) {
- $data = [
- "action" => "download",
- "fileId" => $file->getId()
- ];
-
- $userId = null;
- if (!empty($user)) {
- $userId = $user->getUID();
- $data["userId"] = $userId;
- }
- if ($version > 0) {
- $data["version"] = $version;
- }
-
- $hashUrl = $this->crypt->GetHash($data);
-
- $fileUrl = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.download", ["doc" => $hashUrl]);
-
- if (!$this->config->UseDemo() && !empty($this->config->GetStorageUrl())) {
- $fileUrl = str_replace($this->urlGenerator->getAbsoluteURL("/"), $this->config->GetStorageUrl(), $fileUrl);
- }
-
- return $fileUrl;
- }
-
- /**
- * Generate array with file parameters
- *
- * @param File $file - file
- *
- * @return array
- */
- private function getFileParam($file) {
- if ($file->getSize() === 0) {
- return [null, null, null];
- }
-
- $key = null;
- $versionNum = 0;
- if ($file instanceof MetaFileVersionNode) {
- if ($this->versionManager->available !== true) {
- return [null, null, null];
- }
-
- $fileVersion = $file->getName();
- $sourceFileId = $file->getId();
-
- $storage = $file->getStorage();
- $path = $file->getContentDispositionFileName();
-
- $ownerId = $storage->getOwner($path);
- $owner = $this->userManager->get($ownerId);
- if ($owner === null) {
- return [null, null, null];
- }
-
- $files = $this->root->getUserFolder($ownerId)->getById($sourceFileId);
- if (empty($files)) {
- return [null, null, null];
- }
- $file = $files[0];
-
- $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
-
- foreach ($versions as $version) {
- $versionNum = $versionNum + 1;
-
- $versionId = $version->getRevisionId();
- if (strcmp($versionId, $fileVersion) === 0) {
- $key = $this->fileUtility->getVersionKey($version);
- $key = DocumentService::GenerateRevisionId($key);
-
- break;
- }
- }
- } else {
- $owner = $file->getOwner();
-
- $key = $this->fileUtility->getKey($file);
- $key = DocumentService::GenerateRevisionId($key);
- }
-
- $fileUrl = $this->getUrl($file, $owner, $versionNum);
-
- $fileExtension = strtolower(pathinfo($file->getName(), PATHINFO_EXTENSION));
-
- return [$fileUrl, $fileExtension, $key];
- }
+ /**
+ * Application name
+ *
+ * @var string
+ */
+ private $appName;
+
+ /**
+ * Root folder
+ *
+ * @var IRootFolder
+ */
+ private $root;
+
+ /**
+ * User manager
+ *
+ * @var IUserManager
+ */
+ private $userManager;
+
+ /**
+ * Logger
+ *
+ * @var ILogger
+ */
+ private $logger;
+
+ /**
+ * l10n service
+ *
+ * @var IL10N
+ */
+ private $trans;
+
+ /**
+ * Application configuration
+ *
+ * @var AppConfig
+ */
+ private $config;
+
+ /**
+ * Url generator service
+ *
+ * @var IURLGenerator
+ */
+ private $urlGenerator;
+
+ /**
+ * Hash generator
+ *
+ * @var Crypt
+ */
+ private $crypt;
+
+ /**
+ * File version manager
+ *
+ * @var VersionManager
+ */
+ private $versionManager;
+
+ /**
+ * File utility
+ *
+ * @var FileUtility
+ */
+ private $fileUtility;
+
+ /**
+ * Capabilities mimetype
+ *
+ * @var Array
+ */
+ public static $capabilities = [
+ "text/csv",
+ "application/msword",
+ "application/vnd.ms-word.document.macroEnabled.12",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
+ "application/epub+zip",
+ "text/html",
+ "application/vnd.oasis.opendocument.presentation",
+ "application/vnd.oasis.opendocument.spreadsheet",
+ "application/vnd.oasis.opendocument.text",
+ "application/vnd.oasis.opendocument.presentation-template",
+ "application/vnd.oasis.opendocument.spreadsheet-template",
+ "application/vnd.oasis.opendocument.text-template",
+ "application/pdf",
+ "application/vnd.ms-powerpoint.template.macroEnabled.12",
+ "application/vnd.openxmlformats-officedocument.presentationml.template",
+ "application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
+ "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
+ "application/vnd.ms-powerpoint",
+ "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+ "text/rtf",
+ "text/plain",
+ "application/vnd.ms-excel",
+ "application/vnd.ms-excel.sheet.macroEnabled.12",
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ "application/vnd.ms-excel.template.macroEnabled.12",
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.template"
+ ];
+
+ /**
+ * Converted thumbnail format
+ */
+ private const thumbExtension = "jpeg";
+
+ /**
+ * @param string $appName - application name
+ * @param IRootFolder $root - root folder
+ * @param ILogger $logger - logger
+ * @param IL10N $trans - l10n service
+ * @param AppConfig $config - application configuration
+ * @param IURLGenerator $urlGenerator - url generator service
+ * @param Crypt $crypt - hash generator
+ * @param IManager $shareManager - share manager
+ * @param ISession $session - session
+ * @param IUserManager $userManager - user manager
+ */
+ public function __construct(
+ string $appName,
+ IRootFolder $root,
+ ILogger $logger,
+ IL10N $trans,
+ AppConfig $config,
+ IURLGenerator $urlGenerator,
+ Crypt $crypt,
+ IManager $shareManager,
+ ISession $session,
+ IUserManager $userManager
+ ) {
+ $this->appName = $appName;
+ $this->root = $root;
+ $this->logger = $logger;
+ $this->trans = $trans;
+ $this->config = $config;
+ $this->urlGenerator = $urlGenerator;
+ $this->crypt = $crypt;
+ $this->userManager = $userManager;
+
+ $this->versionManager = new VersionManager($appName, $root);
+
+ $this->fileUtility = new FileUtility($appName, $trans, $logger, $config, $shareManager, $session);
+ }
+
+ /**
+ * Return mime type
+ */
+ public static function getMimeTypeRegex() {
+ $mimeTypeRegex = "";
+ foreach (self::$capabilities as $format) {
+ if (!empty($mimeTypeRegex)) {
+ $mimeTypeRegex = $mimeTypeRegex . "|";
+ }
+ $mimeTypeRegex = $mimeTypeRegex . str_replace("/", "\/", $format);
+ }
+ $mimeTypeRegex = "/" . $mimeTypeRegex . "/";
+
+ return $mimeTypeRegex;
+ }
+
+ /**
+ * Return mime type
+ */
+ public function getMimeType() {
+ $m = self::getMimeTypeRegex();
+ return $m;
+ }
+
+ /**
+ * The method checks if the file can be converted
+ *
+ * @param FileInfo $fileInfo - File
+ *
+ * @return bool
+ */
+ public function isAvailable(FileInfo $fileInfo) {
+ if ($this->config->GetPreview() !== true) {
+ return false;
+ }
+ if (!$fileInfo
+ || $fileInfo->getSize() === 0
+ || $fileInfo->getSize() > $this->config->GetLimitThumbSize()) {
+ return false;
+ }
+ if (!\in_array($fileInfo->getMimetype(), self::$capabilities, true)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * The method is generated thumbnail for file and returned image object
+ *
+ * @param File $file - file
+ * @param int $maxX - The maximum X size of the thumbnail
+ * @param int $maxY - The maximum Y size of the thumbnail
+ * @param bool $scalingup - Disable/Enable upscaling of previews
+ *
+ * @return Image|bool false if no preview was generated
+ */
+ public function getThumbnail($file, $maxX, $maxY, $scalingup) {
+ if (empty($file)) {
+ $this->logger->error("getThumbnail is impossible. File is null", ["app" => $this->appName]);
+ return false;
+ }
+
+ $this->logger->debug("getThumbnail " . $file->getPath() . " $maxX $maxY", ["app" => $this->appName]);
+
+ list($fileUrl, $extension, $key) = $this->getFileParam($file);
+ if ($fileUrl === null || $extension === null || $key === null) {
+ return false;
+ }
+
+ $imageUrl = null;
+ $documentService = new DocumentService($this->trans, $this->config);
+ try {
+ $imageUrl = $documentService->GetConvertedUri($fileUrl, $extension, self::thumbExtension, $key);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "GetConvertedUri: from $extension to " . self::thumbExtension, "app" => $this->appName]);
+ return false;
+ }
+
+ try {
+ $thumbnail = $documentService->Request($imageUrl);
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ["message" => "Failed to download thumbnail", "app" => $this->appName]);
+ return false;
+ }
+
+ $image = new Image();
+ $image->loadFromData($thumbnail);
+
+ if ($image->valid()) {
+ $image->scaleDownToFit($maxX, $maxY);
+ return $image;
+ }
+
+ return false;
+ }
+
+ /**
+ * Generate secure link to download document
+ *
+ * @param File $file - file
+ * @param IUser $user - user with access
+ * @param int $version - file version
+ *
+ * @return string
+ */
+ private function getUrl($file, $user = null, $version = 0) {
+ $data = [
+ "action" => "download",
+ "fileId" => $file->getId()
+ ];
+
+ $userId = null;
+ if (!empty($user)) {
+ $userId = $user->getUID();
+ $data["userId"] = $userId;
+ }
+ if ($version > 0) {
+ $data["version"] = $version;
+ }
+
+ $hashUrl = $this->crypt->GetHash($data);
+
+ $fileUrl = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.download", ["doc" => $hashUrl]);
+
+ if (!$this->config->UseDemo() && !empty($this->config->GetStorageUrl())) {
+ $fileUrl = str_replace($this->urlGenerator->getAbsoluteURL("/"), $this->config->GetStorageUrl(), $fileUrl);
+ }
+
+ return $fileUrl;
+ }
+
+ /**
+ * Generate array with file parameters
+ *
+ * @param File $file - file
+ *
+ * @return array
+ */
+ private function getFileParam($file) {
+ if ($file->getSize() === 0) {
+ return [null, null, null];
+ }
+
+ $key = null;
+ $versionNum = 0;
+ if ($file instanceof MetaFileVersionNode) {
+ if ($this->versionManager->available !== true) {
+ return [null, null, null];
+ }
+
+ $fileVersion = $file->getName();
+ $sourceFileId = $file->getId();
+
+ $storage = $file->getStorage();
+ $path = $file->getContentDispositionFileName();
+
+ $ownerId = $storage->getOwner($path);
+ $owner = $this->userManager->get($ownerId);
+ if ($owner === null) {
+ return [null, null, null];
+ }
+
+ $files = $this->root->getUserFolder($ownerId)->getById($sourceFileId);
+ if (empty($files)) {
+ return [null, null, null];
+ }
+ $file = $files[0];
+
+ $versions = array_reverse($this->versionManager->getVersionsForFile($owner, $file->getFileInfo()));
+
+ foreach ($versions as $version) {
+ $versionNum = $versionNum + 1;
+
+ $versionId = $version->getRevisionId();
+ if (strcmp($versionId, $fileVersion) === 0) {
+ $key = $this->fileUtility->getVersionKey($version);
+ $key = DocumentService::GenerateRevisionId($key);
+
+ break;
+ }
+ }
+ } else {
+ $owner = $file->getOwner();
+
+ $key = $this->fileUtility->getKey($file);
+ $key = DocumentService::GenerateRevisionId($key);
+ }
+
+ $fileUrl = $this->getUrl($file, $owner, $versionNum);
+
+ $fileExtension = strtolower(pathinfo($file->getName(), PATHINFO_EXTENSION));
+
+ return [$fileUrl, $fileExtension, $key];
+ }
}
diff --git a/lib/remoteinstance.php b/lib/remoteinstance.php
index 0d5c00db..8952667c 100644
--- a/lib/remoteinstance.php
+++ b/lib/remoteinstance.php
@@ -29,254 +29,254 @@
* @package OCA\Onlyoffice
*/
class RemoteInstance {
- /**
- * App name
- */
- private const App_Name = "onlyoffice";
-
- /**
- * Table name
- */
- private const TableName_Key = "onlyoffice_instance";
-
- /**
- * Time to live of remote instance (12 hours)
- */
- private static $ttl = 60 * 60 * 12;
-
- /**
- * Health remote list
- */
- private static $healthRemote = [];
-
- /**
- * Get remote instance
- *
- * @param string $remote - remote instance
- *
- * @return array
- */
- private static function get($remote) {
- $connection = \OC::$server->getDatabaseConnection();
- $select = $connection->prepare("
+ /**
+ * App name
+ */
+ private const App_Name = "onlyoffice";
+
+ /**
+ * Table name
+ */
+ private const TableName_Key = "onlyoffice_instance";
+
+ /**
+ * Time to live of remote instance (12 hours)
+ */
+ private static $ttl = 60 * 60 * 12;
+
+ /**
+ * Health remote list
+ */
+ private static $healthRemote = [];
+
+ /**
+ * Get remote instance
+ *
+ * @param string $remote - remote instance
+ *
+ * @return array
+ */
+ private static function get($remote) {
+ $connection = \OC::$server->getDatabaseConnection();
+ $select = $connection->prepare("
SELECT remote, expire, status
FROM `*PREFIX*" . self::TableName_Key . "`
WHERE `remote` = ?
");
- $result = $select->execute([$remote]);
-
- $dbremote = $result ? $select->fetch() : [];
-
- return $dbremote;
- }
-
- /**
- * Store remote instance
- *
- * @param string $remote - remote instance
- * @param bool $status - remote status
- *
- * @return bool
- */
- private static function set($remote, $status) {
- $connection = \OC::$server->getDatabaseConnection();
- $insert = $connection->prepare("
+ $result = $select->execute([$remote]);
+
+ $dbremote = $result ? $select->fetch() : [];
+
+ return $dbremote;
+ }
+
+ /**
+ * Store remote instance
+ *
+ * @param string $remote - remote instance
+ * @param bool $status - remote status
+ *
+ * @return bool
+ */
+ private static function set($remote, $status) {
+ $connection = \OC::$server->getDatabaseConnection();
+ $insert = $connection->prepare("
INSERT INTO `*PREFIX*" . self::TableName_Key . "`
(`remote`, `status`, `expire`)
VALUES (?, ?, ?)
");
- return (bool)$insert->execute([$remote, $status === true ? 1 : 0, time()]);
- }
-
- /**
- * Update remote instance
- *
- * @param string $remote - remote instance
- * @param bool $status - remote status
- *
- * @return bool
- */
- private static function update($remote, $status) {
- $connection = \OC::$server->getDatabaseConnection();
- $update = $connection->prepare("
+ return (bool)$insert->execute([$remote, $status === true ? 1 : 0, time()]);
+ }
+
+ /**
+ * Update remote instance
+ *
+ * @param string $remote - remote instance
+ * @param bool $status - remote status
+ *
+ * @return bool
+ */
+ private static function update($remote, $status) {
+ $connection = \OC::$server->getDatabaseConnection();
+ $update = $connection->prepare("
UPDATE `*PREFIX*" . self::TableName_Key . "`
SET status = ?, expire = ?
WHERE remote = ?
");
- return (bool)$update->execute([$status === true ? 1 : 0, time(), $remote]);
- }
-
- /**
- * Health check remote instance
- *
- * @param string $remote - remote instance
- *
- * @return bool
- */
- public static function healthCheck($remote) {
- $logger = \OC::$server->getLogger();
- $remote = rtrim($remote, "/") . "/";
-
- if (\in_array($remote, self::$healthRemote)) {
- $logger->debug("Remote instance " . $remote . " from local cache status " . $dbremote["status"], ["app" => self::App_Name]);
- return true;
- }
-
- $dbremote = self::get($remote);
- if (!empty($dbremote) && $dbremote["expire"] + self::$ttl > time()) {
- $logger->debug("Remote instance " . $remote . " from database status " . $dbremote["status"], ["app" => self::App_Name]);
- self::$healthRemote[$remote] = $dbremote["status"];
- return self::$healthRemote[$remote];
- }
-
- $httpClientService = \OC::$server->getHTTPClientService();
- $client = $httpClientService->newClient();
-
- $status = false;
- try {
- $response = $client->get($remote . "ocs/v2.php/apps/" . self::App_Name . "/api/v1/healthcheck?format=json");
- $body = json_decode($response->getBody(), true);
-
- $data = $body["ocs"]["data"];
- if (isset($data["alive"])) {
- $status = $data["alive"] === true;
- }
- } catch (\Exception $e) {
- $logger->logException($e, ["message" => "Failed to request federated health check for" . $remote, "app" => self::App_Name]);
- }
-
- if (empty($dbremote)) {
- self::set($remote, $status);
- } else {
- self::update($remote, $status);
- }
-
- $logger->debug("Remote instance " . $remote . " was stored to database status " . $dbremote["status"], ["app" => self::App_Name]);
-
- self::$healthRemote[$remote] = $status;
-
- return self::$healthRemote[$remote];
- }
-
- /**
- * Generate unique document identifier in federated share
- *
- * @param File $file - file
- *
- * @return string
- */
- public function getRemoteKey($file) {
- $logger = \OC::$server->getLogger();
-
- $remote = $file->getStorage()->getRemote();
- $shareToken = $file->getStorage()->getToken();
- $internalPath = $file->getInternalPath();
-
- $httpClientService = \OC::$server->getHTTPClientService();
- $client = $httpClientService->newClient();
-
- try {
- $response = $client->post($remote . "/ocs/v2.php/apps/" . self::App_Name . "/api/v1/key?format=json", [
- "timeout" => 5,
- "json" => [
- "shareToken" => $shareToken,
- "path" => $internalPath
- ]
- ]);
-
- $body = \json_decode($response->getBody(), true);
-
- $data = $body["ocs"]["data"];
- if (!empty($data["error"])) {
- $logger->error("Error federated key " . $data["error"], ["app" => self::App_Name]);
- return null;
- }
-
- $key = $data["key"];
- $logger->debug("Federated key: $key", ["app" => self::App_Name]);
-
- return $key;
- } catch (\Exception $e) {
- $logger->logException($e, ["message" => "Failed to request federated key " . $file->getId(), "app" => self::App_Name]);
-
- if ($e->getResponse()->getStatusCode() === 404) {
- self::update($remote, false);
- $logger->debug("Changed status for remote instance $remote to false", ["app" => self::App_Name]);
- }
-
- return null;
- }
- }
-
- /**
- * Change lock status in the federated share
- *
- * @param File $file - file
- * @param bool $lock - status
- * @param bool $fs - status
- *
- * @return bool
- */
- public static function lockRemoteKey($file, $lock, $fs) {
- $logger = \OC::$server->getLogger();
- $action = $lock ? "lock" : "unlock";
-
- $remote = $file->getStorage()->getRemote();
- $shareToken = $file->getStorage()->getToken();
- $internalPath = $file->getInternalPath();
-
- $httpClientService = \OC::$server->getHTTPClientService();
- $client = $httpClientService->newClient();
- $data = [
- "timeout" => 5,
- "json" => [
- "shareToken" => $shareToken,
- "path" => $internalPath,
- "lock" => $lock
- ]
- ];
- if (!empty($fs)) {
- $data["json"]["fs"] = $fs;
- }
-
- try {
- $response = $client->post($remote . "/ocs/v2.php/apps/" . self::App_Name . "/api/v1/keylock?format=json", $data);
- $body = \json_decode($response->getBody(), true);
-
- $data = $body["ocs"]["data"];
-
- if (empty($data)) {
- $logger->debug("Federated request" . $action . "for " . $file->getFileInfo()->getId() . " is successful", ["app" => self::App_Name]);
- return true;
- }
-
- if (!empty($data["error"])) {
- $logger->error("Error" . $action . "federated key for " . $file->getFileInfo()->getId() . ": " . $data["error"], ["app" => self::App_Name]);
- return false;
- }
- } catch(\Exception $e) {
- $logger->logException($e, ["message" => "Failed to request federated " . $action . " for " . $file->getFileInfo()->getId(), "app" => self::App_Name]);
- return false;
- }
- }
-
- /**
- * Check of federated capable
- *
- * @param File $file - file
- *
- * @return bool
- */
- public static function isRemoteFile($file) {
- $storage = $file->getStorage();
-
- $alive = false;
- $isFederated = $storage->instanceOfStorage(SharingExternalStorage::class);
- if (!$isFederated) {
- return false;
- }
-
- $alive = RemoteInstance::healthCheck($storage->getRemote());
- return $alive;
- }
+ return (bool)$update->execute([$status === true ? 1 : 0, time(), $remote]);
+ }
+
+ /**
+ * Health check remote instance
+ *
+ * @param string $remote - remote instance
+ *
+ * @return bool
+ */
+ public static function healthCheck($remote) {
+ $logger = \OC::$server->getLogger();
+ $remote = rtrim($remote, "/") . "/";
+
+ if (\in_array($remote, self::$healthRemote)) {
+ $logger->debug("Remote instance " . $remote . " from local cache status " . $dbremote["status"], ["app" => self::App_Name]);
+ return true;
+ }
+
+ $dbremote = self::get($remote);
+ if (!empty($dbremote) && $dbremote["expire"] + self::$ttl > time()) {
+ $logger->debug("Remote instance " . $remote . " from database status " . $dbremote["status"], ["app" => self::App_Name]);
+ self::$healthRemote[$remote] = $dbremote["status"];
+ return self::$healthRemote[$remote];
+ }
+
+ $httpClientService = \OC::$server->getHTTPClientService();
+ $client = $httpClientService->newClient();
+
+ $status = false;
+ try {
+ $response = $client->get($remote . "ocs/v2.php/apps/" . self::App_Name . "/api/v1/healthcheck?format=json");
+ $body = json_decode($response->getBody(), true);
+
+ $data = $body["ocs"]["data"];
+ if (isset($data["alive"])) {
+ $status = $data["alive"] === true;
+ }
+ } catch (\Exception $e) {
+ $logger->logException($e, ["message" => "Failed to request federated health check for" . $remote, "app" => self::App_Name]);
+ }
+
+ if (empty($dbremote)) {
+ self::set($remote, $status);
+ } else {
+ self::update($remote, $status);
+ }
+
+ $logger->debug("Remote instance " . $remote . " was stored to database status " . $dbremote["status"], ["app" => self::App_Name]);
+
+ self::$healthRemote[$remote] = $status;
+
+ return self::$healthRemote[$remote];
+ }
+
+ /**
+ * Generate unique document identifier in federated share
+ *
+ * @param File $file - file
+ *
+ * @return string
+ */
+ public function getRemoteKey($file) {
+ $logger = \OC::$server->getLogger();
+
+ $remote = $file->getStorage()->getRemote();
+ $shareToken = $file->getStorage()->getToken();
+ $internalPath = $file->getInternalPath();
+
+ $httpClientService = \OC::$server->getHTTPClientService();
+ $client = $httpClientService->newClient();
+
+ try {
+ $response = $client->post($remote . "/ocs/v2.php/apps/" . self::App_Name . "/api/v1/key?format=json", [
+ "timeout" => 5,
+ "json" => [
+ "shareToken" => $shareToken,
+ "path" => $internalPath
+ ]
+ ]);
+
+ $body = \json_decode($response->getBody(), true);
+
+ $data = $body["ocs"]["data"];
+ if (!empty($data["error"])) {
+ $logger->error("Error federated key " . $data["error"], ["app" => self::App_Name]);
+ return null;
+ }
+
+ $key = $data["key"];
+ $logger->debug("Federated key: $key", ["app" => self::App_Name]);
+
+ return $key;
+ } catch (\Exception $e) {
+ $logger->logException($e, ["message" => "Failed to request federated key " . $file->getId(), "app" => self::App_Name]);
+
+ if ($e->getResponse()->getStatusCode() === 404) {
+ self::update($remote, false);
+ $logger->debug("Changed status for remote instance $remote to false", ["app" => self::App_Name]);
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Change lock status in the federated share
+ *
+ * @param File $file - file
+ * @param bool $lock - status
+ * @param bool $fs - status
+ *
+ * @return bool
+ */
+ public static function lockRemoteKey($file, $lock, $fs) {
+ $logger = \OC::$server->getLogger();
+ $action = $lock ? "lock" : "unlock";
+
+ $remote = $file->getStorage()->getRemote();
+ $shareToken = $file->getStorage()->getToken();
+ $internalPath = $file->getInternalPath();
+
+ $httpClientService = \OC::$server->getHTTPClientService();
+ $client = $httpClientService->newClient();
+ $data = [
+ "timeout" => 5,
+ "json" => [
+ "shareToken" => $shareToken,
+ "path" => $internalPath,
+ "lock" => $lock
+ ]
+ ];
+ if (!empty($fs)) {
+ $data["json"]["fs"] = $fs;
+ }
+
+ try {
+ $response = $client->post($remote . "/ocs/v2.php/apps/" . self::App_Name . "/api/v1/keylock?format=json", $data);
+ $body = \json_decode($response->getBody(), true);
+
+ $data = $body["ocs"]["data"];
+
+ if (empty($data)) {
+ $logger->debug("Federated request" . $action . "for " . $file->getFileInfo()->getId() . " is successful", ["app" => self::App_Name]);
+ return true;
+ }
+
+ if (!empty($data["error"])) {
+ $logger->error("Error" . $action . "federated key for " . $file->getFileInfo()->getId() . ": " . $data["error"], ["app" => self::App_Name]);
+ return false;
+ }
+ } catch(\Exception $e) {
+ $logger->logException($e, ["message" => "Failed to request federated " . $action . " for " . $file->getFileInfo()->getId(), "app" => self::App_Name]);
+ return false;
+ }
+ }
+
+ /**
+ * Check of federated capable
+ *
+ * @param File $file - file
+ *
+ * @return bool
+ */
+ public static function isRemoteFile($file) {
+ $storage = $file->getStorage();
+
+ $alive = false;
+ $isFederated = $storage->instanceOfStorage(SharingExternalStorage::class);
+ if (!$isFederated) {
+ return false;
+ }
+
+ $alive = RemoteInstance::healthCheck($storage->getRemote());
+ return $alive;
+ }
}
diff --git a/lib/templatemanager.php b/lib/templatemanager.php
index c90a9e4f..16e35515 100644
--- a/lib/templatemanager.php
+++ b/lib/templatemanager.php
@@ -28,190 +28,190 @@
* @package OCA\Onlyoffice
*/
class TemplateManager {
- /**
- * Application name
- *
- * @var string
- */
- private static $appName = "onlyoffice";
-
- /**
- * Template folder name
- *
- * @var string
- */
- private static $templateFolderName = "template";
-
- /**
- * Get global template directory
- *
- * @return Folder
- */
- public static function GetGlobalTemplateDir() {
- $dirPath = self::$appName . "/" . self::$templateFolderName;
-
- $rootFolder = \OC::$server->getRootFolder();
- $templateDir = null;
- try {
- $templateDir = $rootFolder->get($dirPath);
- } catch (NotFoundException $e) {
- $templateDir = $rootFolder->newFolder($dirPath);
- }
-
- return $templateDir;
- }
-
- /**
- * Get global templates
- *
- * @param string $mimetype - mimetype of the template
- *
- * @return array
- */
- public static function GetGlobalTemplates($mimetype = null) {
- $templateDir = self::GetGlobalTemplateDir();
-
- $templatesList = $templateDir->getDirectoryListing();
- if (!empty($mimetype)
- && \is_array($templatesList) && \count($templatesList) > 0) {
- $templatesList = $templateDir->searchByMime($mimetype);
- }
-
- return $templatesList;
- }
-
- /**
- * Get template file
- *
- * @param string $templateId - identifier file template
- *
- * @return File
- */
- public static function GetTemplate($templateId) {
- $logger = \OC::$server->getLogger();
-
- $templateDir = self::GetGlobalTemplateDir();
- try {
- $templates = $templateDir->getById($templateId);
- } catch(\Exception $e) {
- $logger->logException($e, ["message" => "GetTemplate: $templateId", "app" => self::$appName]);
- return null;
- }
-
- if (empty($templates)) {
- $logger->info("Template not found: $templateId", ["app" => self::$appName]);
- return null;
- }
-
- return $templates[0];
- }
-
- /**
- * Get type template from mimetype
- *
- * @param string $mime - mimetype
- *
- * @return string
- */
- public static function GetTypeTemplate($mime) {
- switch($mime) {
- case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
- return "document";
- case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
- return "spreadsheet";
- case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
- return "presentation";
- }
-
- return "";
- }
-
- /**
- * Check template type
- *
- * @param string $name - template name
- *
- * @return bool
- */
- public static function IsTemplateType($name) {
- $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
- switch($ext) {
- case "docx":
- case "xlsx":
- case "pptx":
- return true;
- }
-
- return false;
- }
-
- /**
- * Get empty template content
- *
- * @param string $fileName - target file name
- *
- * @return string
- */
- public static function GetEmptyTemplate($fileName) {
- $ext = strtolower("." . pathinfo($fileName, PATHINFO_EXTENSION));
- $lang = \OC::$server->getL10NFactory("")->get("")->getLanguageCode();
-
- $templatePath = self::GetEmptyTemplatePath($lang, $ext);
-
- $template = file_get_contents($templatePath);
- return $template;
- }
-
- /**
- * Get template path
- *
- * @param string $lang - language
- * @param string $ext - file extension
- *
- * @return string
- */
- public static function GetEmptyTemplatePath($lang, $ext) {
- if (!\array_key_exists($lang, self::$localPath)) {
- $lang = "en";
- }
-
- return \dirname(__DIR__) . DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR . self::$localPath[$lang] . DIRECTORY_SEPARATOR . "new" . $ext;
- }
-
- /**
- * Mapping local path to templates
- *
- * @var Array
- */
- private static $localPath = [
- "az" => "az-Latn-AZ",
- "bg_BG" => "bg-BG",
- "cs" => "cs-CZ",
- "de" => "de-DE",
- "de_DE" => "de-DE",
- "el" => "el-GR",
- "en" => "en-US",
- "en_GB" => "en-GB",
- "es" => "es-ES",
- "eu" => "eu-ES",
- "fr" => "fr-FR",
- "gl" => "gl-ES",
- "it" => "it-IT",
- "ja" => "ja-JP",
- "ko" => "ko-KR",
- "lv" => "lv-LV",
- "nl" => "nl-NL",
- "pl" => "pl-PL",
- "pt_BR" => "pt-BR",
- "pt_PT" => "pt-PT",
- "ru" => "ru-RU",
- "si_LK" => "si-LK",
- "sk_SK" => "sk-SK",
- "sv" => "sv-SE",
- "tr" => "tr-TR",
- "uk" => "uk-UA",
- "vi" => "vi-VN",
- "zh_CN" => "zh-CN",
- "zh_TW" => "zh-TW"
- ];
+ /**
+ * Application name
+ *
+ * @var string
+ */
+ private static $appName = "onlyoffice";
+
+ /**
+ * Template folder name
+ *
+ * @var string
+ */
+ private static $templateFolderName = "template";
+
+ /**
+ * Get global template directory
+ *
+ * @return Folder
+ */
+ public static function GetGlobalTemplateDir() {
+ $dirPath = self::$appName . "/" . self::$templateFolderName;
+
+ $rootFolder = \OC::$server->getRootFolder();
+ $templateDir = null;
+ try {
+ $templateDir = $rootFolder->get($dirPath);
+ } catch (NotFoundException $e) {
+ $templateDir = $rootFolder->newFolder($dirPath);
+ }
+
+ return $templateDir;
+ }
+
+ /**
+ * Get global templates
+ *
+ * @param string $mimetype - mimetype of the template
+ *
+ * @return array
+ */
+ public static function GetGlobalTemplates($mimetype = null) {
+ $templateDir = self::GetGlobalTemplateDir();
+
+ $templatesList = $templateDir->getDirectoryListing();
+ if (!empty($mimetype)
+ && \is_array($templatesList) && \count($templatesList) > 0) {
+ $templatesList = $templateDir->searchByMime($mimetype);
+ }
+
+ return $templatesList;
+ }
+
+ /**
+ * Get template file
+ *
+ * @param string $templateId - identifier file template
+ *
+ * @return File
+ */
+ public static function GetTemplate($templateId) {
+ $logger = \OC::$server->getLogger();
+
+ $templateDir = self::GetGlobalTemplateDir();
+ try {
+ $templates = $templateDir->getById($templateId);
+ } catch(\Exception $e) {
+ $logger->logException($e, ["message" => "GetTemplate: $templateId", "app" => self::$appName]);
+ return null;
+ }
+
+ if (empty($templates)) {
+ $logger->info("Template not found: $templateId", ["app" => self::$appName]);
+ return null;
+ }
+
+ return $templates[0];
+ }
+
+ /**
+ * Get type template from mimetype
+ *
+ * @param string $mime - mimetype
+ *
+ * @return string
+ */
+ public static function GetTypeTemplate($mime) {
+ switch($mime) {
+ case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
+ return "document";
+ case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
+ return "spreadsheet";
+ case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
+ return "presentation";
+ }
+
+ return "";
+ }
+
+ /**
+ * Check template type
+ *
+ * @param string $name - template name
+ *
+ * @return bool
+ */
+ public static function IsTemplateType($name) {
+ $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
+ switch($ext) {
+ case "docx":
+ case "xlsx":
+ case "pptx":
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get empty template content
+ *
+ * @param string $fileName - target file name
+ *
+ * @return string
+ */
+ public static function GetEmptyTemplate($fileName) {
+ $ext = strtolower("." . pathinfo($fileName, PATHINFO_EXTENSION));
+ $lang = \OC::$server->getL10NFactory("")->get("")->getLanguageCode();
+
+ $templatePath = self::GetEmptyTemplatePath($lang, $ext);
+
+ $template = file_get_contents($templatePath);
+ return $template;
+ }
+
+ /**
+ * Get template path
+ *
+ * @param string $lang - language
+ * @param string $ext - file extension
+ *
+ * @return string
+ */
+ public static function GetEmptyTemplatePath($lang, $ext) {
+ if (!\array_key_exists($lang, self::$localPath)) {
+ $lang = "en";
+ }
+
+ return \dirname(__DIR__) . DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR . self::$localPath[$lang] . DIRECTORY_SEPARATOR . "new" . $ext;
+ }
+
+ /**
+ * Mapping local path to templates
+ *
+ * @var Array
+ */
+ private static $localPath = [
+ "az" => "az-Latn-AZ",
+ "bg_BG" => "bg-BG",
+ "cs" => "cs-CZ",
+ "de" => "de-DE",
+ "de_DE" => "de-DE",
+ "el" => "el-GR",
+ "en" => "en-US",
+ "en_GB" => "en-GB",
+ "es" => "es-ES",
+ "eu" => "eu-ES",
+ "fr" => "fr-FR",
+ "gl" => "gl-ES",
+ "it" => "it-IT",
+ "ja" => "ja-JP",
+ "ko" => "ko-KR",
+ "lv" => "lv-LV",
+ "nl" => "nl-NL",
+ "pl" => "pl-PL",
+ "pt_BR" => "pt-BR",
+ "pt_PT" => "pt-PT",
+ "ru" => "ru-RU",
+ "si_LK" => "si-LK",
+ "sk_SK" => "sk-SK",
+ "sv" => "sv-SE",
+ "tr" => "tr-TR",
+ "uk" => "uk-UA",
+ "vi" => "vi-VN",
+ "zh_CN" => "zh-CN",
+ "zh_TW" => "zh-TW"
+ ];
}
diff --git a/lib/version.php b/lib/version.php
index c5a6f981..c89b894f 100644
--- a/lib/version.php
+++ b/lib/version.php
@@ -27,84 +27,84 @@
* @package OCA\Onlyoffice
*/
class Version {
- /**
- * Time of creation
- *
- * @var int
- * */
- private $timestamp;
+ /**
+ * Time of creation
+ *
+ * @var int
+ * */
+ private $timestamp;
- /**
- * Version file
- *
- * @var int|string
- * */
- private $revisionId;
+ /**
+ * Version file
+ *
+ * @var int|string
+ * */
+ private $revisionId;
- /**
- * File path
- *
- * @var string
- * */
- private $path;
+ /**
+ * File path
+ *
+ * @var string
+ * */
+ private $path;
- /**
- * Source file properties
- *
- * @var FileInfo
- * */
- private $sourceFileInfo;
+ /**
+ * Source file properties
+ *
+ * @var FileInfo
+ * */
+ private $sourceFileInfo;
- /**
- * @param int $timestamp - file time stamp
- * @param int $revisionId - revision id
- * @param FileInfo $sourceFileInfo - source file info
- */
- public function __construct(
- int $timestamp,
- int $revisionId,
- string $path,
- FileInfo $sourceFileInfo
- ) {
- $this->timestamp = $timestamp;
- $this->revisionId = $revisionId;
- $this->path = $path;
- $this->sourceFileInfo = $sourceFileInfo;
- }
+ /**
+ * @param int $timestamp - file time stamp
+ * @param int $revisionId - revision id
+ * @param FileInfo $sourceFileInfo - source file info
+ */
+ public function __construct(
+ int $timestamp,
+ int $revisionId,
+ string $path,
+ FileInfo $sourceFileInfo
+ ) {
+ $this->timestamp = $timestamp;
+ $this->revisionId = $revisionId;
+ $this->path = $path;
+ $this->sourceFileInfo = $sourceFileInfo;
+ }
- /**
- * Get source file
- *
- * @return FileInfo
- */
- public function getSourceFile() {
- return $this->sourceFileInfo;
- }
+ /**
+ * Get source file
+ *
+ * @return FileInfo
+ */
+ public function getSourceFile() {
+ return $this->sourceFileInfo;
+ }
- /**
- * Get version file
- *
- * @return int|string
- */
- public function getRevisionId() {
- return $this->revisionId;
- }
+ /**
+ * Get version file
+ *
+ * @return int|string
+ */
+ public function getRevisionId() {
+ return $this->revisionId;
+ }
- /**
- * Get timestamp file
- *
- * @return int
- */
- public function getTimestamp() {
- return $this->timestamp;
- }
+ /**
+ * Get timestamp file
+ *
+ * @return int
+ */
+ public function getTimestamp() {
+ return $this->timestamp;
+ }
- /**
- * Get file path
- *
- * @return string
- */
- public function getPath() {
- return $this->path;
- }
+ /**
+ * Get file path
+ *
+ * @return string
+ */
+ public function getPath() {
+ return $this->path;
+ }
}
diff --git a/lib/versionmanager.php b/lib/versionmanager.php
index 6598afe4..f71a9230 100644
--- a/lib/versionmanager.php
+++ b/lib/versionmanager.php
@@ -36,155 +36,155 @@
* @package OCA\Onlyoffice
*/
class VersionManager {
- /**
- * Application name
- *
- * @var string
- */
- private $appName;
-
- /**
- * Root folder
- *
- * @var IRootFolder
- */
- private $rootFolder;
-
- /**
- * File versions storage
- *
- * @var Storage
- */
- private $storage;
-
- /**
- * Version manager is available
- *
- * @var bool
- */
- public $available;
-
- /**
- * @param string $AppName - application name
- * @param IRootFolder $rootFolder - root folder
- */
- public function __construct(string $AppName, IRootFolder $rootFolder) {
- $this->appName = $AppName;
- $this->rootFolder = $rootFolder;
-
- if (\OC::$server->getAppManager()->isInstalled("files_versions")) {
- try {
- $this->storage = \OC::$server->query(Storage::class);
- $this->available = true;
- } catch (QueryException $e) {
- \OC::$server->getLogger()->logException($e, ["message" => "VersionManager init error", "app" => $this->appName]);
- }
- }
- }
-
- /**
- * Get version folder
- *
- * @param IUser $user - file owner
- *
- * @return Folder
- */
- private function getVersionFolder($user) {
- $userRoot = $this->rootFolder->getUserFolder($user->getUID())->getParent();
- try {
- $folder = $userRoot->get("files_versions");
- return $folder;
- } catch (NotFoundException $e) {
- \OC::$server->getLogger()->logException($e, ["message" => "VersionManager: not found user version folder " . $user->getUID(), "app" => $this->appName]);
- return null;
- }
- }
-
- /**
- * Get file version
- *
- * @param IUser $user - file owner
- * @param FileInfo $sourceFile - file
- * @param integer $version - file version
- *
- * @return File
- */
- public function getVersionFile($user, $sourceFile, $version) {
- $userFolder = $this->rootFolder->getUserFolder($user->getUID());
- $versionsFolder = $this->getVersionFolder($user);
-
- $file = $versionsFolder->get($userFolder->getRelativePath($sourceFile->getPath()) . ".v" . $version);
- return $file;
- }
-
- /**
- * Get versions for file
- *
- * @param IUser $user - file owner
- * @param FileInfo $file - file
- *
- * @return array
- */
- public function getVersionsForFile($user, $file) {
- $versions = [];
-
- $fileId = $file->getId();
-
- try {
- $userFolder = $this->rootFolder->getUserFolder($user->getUID());
- $nodes = $userFolder->getById($fileId);
- $sourceFile = $nodes[0];
- } catch (\Exception $e) {
- \OC::$server->getLogger()->logException($e, ["message" => "VersionManager: $fileId", "app" => $this->appName]);
- return $versions;
- }
-
- $owner = $sourceFile->getOwner();
- if ($owner === null) {
- return $versions;
- }
-
- $ownerId = $owner->getUID();
- $userFolder = $this->rootFolder->getUserFolder($ownerId);
- $sourceFilePath = $userFolder->getRelativePath($sourceFile->getPath());
- $propsVersions = $this->storage->getVersions($ownerId, $sourceFilePath);
-
- foreach ($propsVersions as $propVersion) {
- $version = new Version(
- $propVersion["timestamp"],
- $propVersion["version"],
- $propVersion["path"],
- $file
- );
-
- array_push($versions, $version);
- }
-
- return $versions;
- }
-
- /**
- * Restore version
- *
- * @param Version $version - version for restore
- *
- */
- public function rollback($version) {
- $sourceFile = $version->getSourceFile();
-
- $ownerId = null;
- $owner = $sourceFile->getOwner();
- if (!empty($owner)) {
- $ownerId = $owner->getUID();
- }
-
- $path = $version->getPath();
- $revision = $version->getTimestamp();
-
- $versionFile = $this->getVersionFile($owner, $sourceFile, $revision);
- $versionFileInfo = $versionFile->getFileInfo();
- $versionPath = $versionFileInfo->getInternalPath();
-
- $this->storage->restoreVersion($ownerId, $path, $versionPath, $revision);
- }
+ /**
+ * Application name
+ *
+ * @var string
+ */
+ private $appName;
+
+ /**
+ * Root folder
+ *
+ * @var IRootFolder
+ */
+ private $rootFolder;
+
+ /**
+ * File versions storage
+ *
+ * @var Storage
+ */
+ private $storage;
+
+ /**
+ * Version manager is available
+ *
+ * @var bool
+ */
+ public $available;
+
+ /**
+ * @param string $AppName - application name
+ * @param IRootFolder $rootFolder - root folder
+ */
+ public function __construct(string $AppName, IRootFolder $rootFolder) {
+ $this->appName = $AppName;
+ $this->rootFolder = $rootFolder;
+
+ if (\OC::$server->getAppManager()->isInstalled("files_versions")) {
+ try {
+ $this->storage = \OC::$server->query(Storage::class);
+ $this->available = true;
+ } catch (QueryException $e) {
+ \OC::$server->getLogger()->logException($e, ["message" => "VersionManager init error", "app" => $this->appName]);
+ }
+ }
+ }
+
+ /**
+ * Get version folder
+ *
+ * @param IUser $user - file owner
+ *
+ * @return Folder
+ */
+ private function getVersionFolder($user) {
+ $userRoot = $this->rootFolder->getUserFolder($user->getUID())->getParent();
+ try {
+ $folder = $userRoot->get("files_versions");
+ return $folder;
+ } catch (NotFoundException $e) {
+ \OC::$server->getLogger()->logException($e, ["message" => "VersionManager: not found user version folder " . $user->getUID(), "app" => $this->appName]);
+ return null;
+ }
+ }
+
+ /**
+ * Get file version
+ *
+ * @param IUser $user - file owner
+ * @param FileInfo $sourceFile - file
+ * @param integer $version - file version
+ *
+ * @return File
+ */
+ public function getVersionFile($user, $sourceFile, $version) {
+ $userFolder = $this->rootFolder->getUserFolder($user->getUID());
+ $versionsFolder = $this->getVersionFolder($user);
+
+ $file = $versionsFolder->get($userFolder->getRelativePath($sourceFile->getPath()) . ".v" . $version);
+ return $file;
+ }
+
+ /**
+ * Get versions for file
+ *
+ * @param IUser $user - file owner
+ * @param FileInfo $file - file
+ *
+ * @return array
+ */
+ public function getVersionsForFile($user, $file) {
+ $versions = [];
+
+ $fileId = $file->getId();
+
+ try {
+ $userFolder = $this->rootFolder->getUserFolder($user->getUID());
+ $nodes = $userFolder->getById($fileId);
+ $sourceFile = $nodes[0];
+ } catch (\Exception $e) {
+ \OC::$server->getLogger()->logException($e, ["message" => "VersionManager: $fileId", "app" => $this->appName]);
+ return $versions;
+ }
+
+ $owner = $sourceFile->getOwner();
+ if ($owner === null) {
+ return $versions;
+ }
+
+ $ownerId = $owner->getUID();
+ $userFolder = $this->rootFolder->getUserFolder($ownerId);
+ $sourceFilePath = $userFolder->getRelativePath($sourceFile->getPath());
+ $propsVersions = $this->storage->getVersions($ownerId, $sourceFilePath);
+
+ foreach ($propsVersions as $propVersion) {
+ $version = new Version(
+ $propVersion["timestamp"],
+ $propVersion["version"],
+ $propVersion["path"],
+ $file
+ );
+
+ array_push($versions, $version);
+ }
+
+ return $versions;
+ }
+
+ /**
+ * Restore version
+ *
+ * @param Version $version - version for restore
+ *
+ */
+ public function rollback($version) {
+ $sourceFile = $version->getSourceFile();
+
+ $ownerId = null;
+ $owner = $sourceFile->getOwner();
+ if (!empty($owner)) {
+ $ownerId = $owner->getUID();
+ }
+
+ $path = $version->getPath();
+ $revision = $version->getTimestamp();
+
+ $versionFile = $this->getVersionFile($owner, $sourceFile, $revision);
+ $versionFileInfo = $versionFile->getFileInfo();
+ $versionPath = $versionFileInfo->getInternalPath();
+
+ $this->storage->restoreVersion($ownerId, $path, $versionPath, $revision);
+ }
}