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

github.com/ONLYOFFICE/onlyoffice-nextcloud.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'controller/editorcontroller.php')
-rw-r--r--controller/editorcontroller.php323
1 files changed, 298 insertions, 25 deletions
diff --git a/controller/editorcontroller.php b/controller/editorcontroller.php
index 2b6f4e5..55581aa 100644
--- a/controller/editorcontroller.php
+++ b/controller/editorcontroller.php
@@ -21,6 +21,7 @@ namespace OCA\Onlyoffice\Controller;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\ContentSecurityPolicy;
+use OCP\AppFramework\Http\DataDownloadResponse;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\Template\PublicTemplateResponse;
@@ -34,11 +35,14 @@ use OCP\IL10N;
use OCP\ILogger;
use OCP\IRequest;
use OCP\ISession;
+use OCP\ITags;
+use OCP\ITagManager;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Share\IManager;
+use OCP\Share\IShare;
use OCA\Files\Helper;
use OCA\Files_Versions\Versions\IVersionManager;
@@ -126,6 +130,20 @@ class EditorController extends Controller {
private $versionManager;
/**
+ * Share manager
+ *
+ * @var IManager
+ */
+ private $shareManager;
+
+ /**
+ * 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
*/
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";
@@ -143,6 +161,7 @@ class EditorController extends Controller {
* @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,
@@ -155,7 +174,8 @@ class EditorController extends Controller {
AppConfig $config,
Crypt $crypt,
IManager $shareManager,
- ISession $session
+ ISession $session,
+ ITagManager $tagManager
) {
parent::__construct($AppName, $request);
@@ -167,6 +187,8 @@ class EditorController extends Controller {
$this->logger = $logger;
$this->config = $config;
$this->crypt = $crypt;
+ $this->shareManager = $shareManager;
+ $this->tagManager = $tagManager;
if (\OC::$server->getAppManager()->isInstalled("files_versions")) {
try {
@@ -231,7 +253,7 @@ class EditorController extends Controller {
$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()) {
+ 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")];
}
@@ -239,7 +261,10 @@ class EditorController extends Controller {
if (empty($templateId)) {
$template = TemplateManager::GetEmptyTemplate($name);
} else {
- $template = TemplateManager::GetTemplate($templateId);
+ $templateFile = TemplateManager::GetTemplate($templateId);
+ if ($templateFile !== null) {
+ $template = $templateFile->getContent();
+ }
}
if (!$template) {
@@ -273,16 +298,17 @@ class EditorController extends Controller {
*
* @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) {
+ public function createNew($name, $dir, $templateId = null) {
$this->logger->debug("Create from editor: $name in $dir", ["app" => $this->appName]);
- $result = $this->create($name, $dir);
+ $result = $this->create($name, $dir, $templateId);
if (isset($result["error"])) {
return $this->renderError($result["error"]);
}
@@ -292,6 +318,128 @@ class EditorController extends Controller {
}
/**
+ * Get users
+ *
+ * @return array
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ */
+ public function users() {
+ $this->logger->debug("Search users", ["app" => $this->appName]);
+ $result = [];
+
+ if (!$this->config->isUserAllowedToUse()) {
+ return $result;
+ }
+
+ $userId = $this->userSession->getUser()->getUID();
+ $users = $this->userManager->search("");
+ foreach ($users as $user) {
+ $email = $user->getEMailAddress();
+ if ($user->getUID() != $userId
+ && !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")];
+ }
+
+ $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
+ ]);
+
+ $canShare = ($file->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE;
+
+ $accessList = $this->shareManager->getAccessList($file);
+
+ foreach ($recipientIds as $recipientId) {
+ if (!in_array($recipientId, $accessList["users"])) {
+ if (!$canShare) {
+ continue;
+ }
+
+ $share = $this->shareManager->newShare();
+ $share->setNode($file)
+ ->setShareType(IShare::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")];
+ }
+
+ /**
* Conversion file to Office Open XML format
*
* @param integer $fileId - file identifier
@@ -362,7 +510,7 @@ class EditorController extends Controller {
}
$folder = $file->getParent();
- if (!$folder->isCreatable()) {
+ if (!($folder->isCreatable() && $folder->isUpdateable())) {
$folder = $this->root->getUserFolder($userId);
}
@@ -418,7 +566,7 @@ class EditorController extends Controller {
$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()) {
+ 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")];
}
@@ -464,6 +612,10 @@ class EditorController extends Controller {
public function history($fileId, $shareToken = null) {
$this->logger->debug("Request history for: $fileId", ["app" => $this->appName]);
+ if (empty($shareToken) && !$this->config->isUserAllowedToUse()) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
$history = [];
$user = $this->userSession->getUser();
@@ -581,6 +733,10 @@ class EditorController extends Controller {
public function version($fileId, $version, $shareToken = null) {
$this->logger->debug("Request version for: $fileId ($version)", ["app" => $this->appName]);
+ if (empty($shareToken) && !$this->config->isUserAllowedToUse()) {
+ return ["error" => $this->trans->t("Not permitted")];
+ }
+
$version = empty($version) ? null : $version;
$user = $this->userSession->getUser();
@@ -711,6 +867,84 @@ class EditorController extends Controller {
}
/**
+ * Download method
+ *
+ * @param int $fileId - file identifier
+ * @param string $toExtension - file extension to download
+ * @param bool $template - file extension to download
+ *
+ * @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);
+ }
+ }
+
+ $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
@@ -719,13 +953,14 @@ class EditorController extends Controller {
* @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) {
+ 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]);
$isLoggedIn = $this->userSession->isLoggedIn();
@@ -755,7 +990,8 @@ class EditorController extends Controller {
"directToken" => null,
"version" => $version,
"isTemplate" => $template,
- "inframe" => false
+ "inframe" => false,
+ "anchor" => $anchor
];
$response = null;
@@ -808,19 +1044,6 @@ class EditorController extends Controller {
}
/**
- * Get template loader Onlyoffice
- *
- * @return TemplateResponse
- *
- * @NoAdminRequired
- * @NoCSRFRequired
- * @PublicPage
- */
- public function loader() {
- return new TemplateResponse($this->appName, "loader", [], "plain");
- }
-
- /**
* Collecting the file parameters for the document service
*
* @param integer $fileId - file identifier
@@ -832,13 +1055,14 @@ class EditorController extends Controller {
* @param bool $desktop - desktop label
* @param string $guestName - nickname not logged user
* @param bool $template - file is template
+ * @param string $anchor - anchor for file content
*
* @return array
*
* @NoAdminRequired
* @PublicPage
*/
- public function config($fileId, $filePath = null, $shareToken = null, $directToken = null, $version = 0, $inframe = false, $desktop = false, $guestName = null, $template = false) {
+ public function config($fileId, $filePath = null, $shareToken = null, $directToken = null, $version = 0, $inframe = false, $desktop = false, $guestName = null, $template = false, $anchor = null) {
if (!empty($directToken)) {
list ($directData, $error) = $this->crypt->ReadHash($directToken);
@@ -885,7 +1109,7 @@ class EditorController extends Controller {
$fileName = $file->getName();
$ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
- $format = $this->config->FormatsSetting()[$ext];
+ $format = !empty($ext) ? $this->config->FormatsSetting()[$ext] : null;
if (!isset($format)) {
$this->logger->info("Format is not supported for editing: $fileName", ["app" => $this->appName]);
return ["error" => $this->trans->t("Format is not supported")];
@@ -1025,9 +1249,32 @@ class EditorController extends Controller {
$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) {
+ if ($folderLink !== null
+ && $this->config->GetSystemValue($this->config->_customization_goback) !== false) {
$params["editorConfig"]["customization"]["goback"] = [
"url" => $folderLink
];
@@ -1055,6 +1302,16 @@ class EditorController extends Controller {
$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());
$params["token"] = $token;
@@ -1371,6 +1628,22 @@ class EditorController extends Controller {
}
/**
+ * 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(ITags::TAG_FAVORITE, $currentTags[$fileId]);
+ }
+
+ return false;
+ }
+
+ /**
* Print error page
*
* @param string $error - error message