diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 1b285dfe54..e205012df3 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -22,6 +22,7 @@ use OCA\Richdocuments\Listener\ReferenceListener; use OCA\Richdocuments\Listener\RegisterTemplateFileCreatorListener; use OCA\Richdocuments\Listener\ShareLinkListener; +use OCA\Richdocuments\Listener\RegisterDirectEditorEventListener; use OCA\Richdocuments\Middleware\WOPIMiddleware; use OCA\Richdocuments\Preview\EMF; use OCA\Richdocuments\Preview\MSExcel; @@ -40,6 +41,7 @@ use OCP\Collaboration\Reference\RenderReferenceEvent; use OCP\Collaboration\Resources\LoadAdditionalScriptsEvent; use OCP\Files\Template\BeforeGetTemplatesEvent; +use OCP\DirectEditing\RegisterDirectEditorEvent; use OCP\Files\Template\FileCreatedFromTemplateEvent; use OCP\Files\Template\RegisterTemplateCreatorEvent; use OCP\Preview\BeforePreviewFetchedEvent; @@ -80,6 +82,7 @@ public function register(IRegistrationContext $context): void { $context->registerPreviewProvider(OOXML::class, OOXML::MIMETYPE_REGEX); $context->registerPreviewProvider(OpenDocument::class, OpenDocument::MIMETYPE_REGEX); $context->registerPreviewProvider(Pdf::class, Pdf::MIMETYPE_REGEX); + $context->registerEventListener(RegisterDirectEditorEvent::class, RegisterDirectEditorEventListener::class); } public function boot(IBootContext $context): void { diff --git a/lib/DirectEditing/DirectEditor.php b/lib/DirectEditing/DirectEditor.php new file mode 100644 index 0000000000..78b1f9bad4 --- /dev/null +++ b/lib/DirectEditing/DirectEditor.php @@ -0,0 +1,198 @@ + + * + * @author Raul Ferreira Fuentes + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Richdocuments\DirectEditing; + +use OCA\Richdocuments\AppConfig; +use OCA\Richdocuments\AppInfo\Application; +use OCA\Richdocuments\Capabilities; +use OCA\Richdocuments\Controller\DocumentTrait; +use OCA\Richdocuments\Service\InitialStateService; +use OCA\Richdocuments\TokenManager; +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\AppFramework\Http\Response; +use OCP\AppFramework\Http\TemplateResponse; +use OCP\DirectEditing\IEditor; +use OCP\DirectEditing\IToken; +use OCP\Files\InvalidPathException; +use OCP\Files\IRootFolder; +use OCP\Files\NotFoundException; +use OCP\Files\NotPermittedException; +use OCP\IConfig; +use OCP\IInitialStateService; +use OCP\IL10N; +use Psr\Log\LoggerInterface; + +class DirectEditor implements IEditor { + use DocumentTrait; + + /** @var IL10N */ + private $l10n; + + /** @var IInitialStateService */ + private $initialStateService; + + /** @var string[] */ + private $mimetypes; + + /** @var TokenManager */ + private $tokenManager; + + /** @var IRootFolder */ + private $rootFolder; + + /** @var IConfig */ + private $config; + + /** @var AppConfig */ + private $appConfig; + + /** @var LoggerInterface */ + private $logger; + + + public function __construct( + IL10N $l10n, + InitialStateService $initialStateService, + Capabilities $capabilities, + TokenManager $tokenManager, + IConfig $config, + AppConfig $appConfig, + IRootFolder $rootFolder, + LoggerInterface $logger + ) { + $this->l10n = $l10n; + $this->initialStateService = $initialStateService; + $this->mimetypes = $capabilities->getCapabilities()[Application::APPNAME]['mimetypes']; + $this->tokenManager = $tokenManager; + $this->config = $config; + $this->appConfig = $appConfig; + $this->rootFolder = $rootFolder; + $this->logger = $logger; + } + + /** + * Return a unique identifier for the editor + * + * e.g. richdocuments + * + * @return string + */ + public function getId(): string { + return Application::APPNAME; + } + + /** + * Return a readable name for the editor + * + * e.g. Collabora Online + * + * @return string + */ + public function getName(): string { + return $this->l10n->t('Nextcloud Office'); + } + + /** + * A list of mimetypes that should open the editor by default + * + * @return array + */ + public function getMimetypes(): array { + return $this->mimetypes; + } + + /** + * A list of mimetypes that can be opened in the editor optionally + * + * @return array + */ + public function getMimetypesOptional(): array { + return []; + } + + /** + * Return a list of file creation options to be presented to the user + * + * @return array of ACreateFromTemplate|ACreateEmpty + */ + public function getCreators(): array { + return [ + new GraphicsCreator($this->l10n), + new PresentationCreator($this->l10n), + new SpreadsheetCreator($this->l10n), + new TextCreator($this->l10n), + ]; + } + + /** + * Return if the view is able to securely view a file without downloading it to the browser + * + * @return bool + */ + public function isSecure(): bool { + return true; + } + + /** + * Return a template response for displaying the editor + * + * open can only be called once when the client requests the editor with a one-time-use token + * For handling editing and later requests, editors need to impelement their own token handling and take care of invalidation + * + * This behavior is similar to the current direct editing implementation in collabora where we generate a one-time token and switch over to the regular wopi token for the actual editing/saving process + * + * @param IToken $token + * @return Response + */ + public function open(IToken $token): Response { + $token->useTokenScope(); + try { + $folder = $this->rootFolder->getUserFolder($token->getUser()); + $item = $token->getFile(); + + [$urlSrc, $token, $wopi] = $this->tokenManager->getToken($item->getId(), null, $token->getUser(), true); + + $params = [ + 'permissions' => $item->getPermissions(), + 'title' => $item->getName(), + 'fileId' => $wopi->getFileid() . '_' . $this->config->getSystemValue('instanceid'), + 'token' => $wopi->getToken(), + 'token_ttl' => $wopi->getExpiry(), + 'urlsrc' => $urlSrc, + 'path' => $folder->getRelativePath($item->getPath()), + 'instanceId' => $this->config->getSystemValue('instanceid'), + 'canonical_webroot' => $this->appConfig->getAppValue('canonical_webroot'), + 'direct' => true, + ]; + + $this->initialStateService->provideDocument($wopi); + $response = new TemplateResponse('richdocuments', 'documents', $params, 'base'); + $this->applyPolicies($response); + return $response; + } catch (InvalidPathException|NotFoundException|NotPermittedException $e) { + $this->logger->error($e->getMessage()); + } + return new NotFoundResponse(); + } +} diff --git a/lib/DirectEditing/GraphicsCreator.php b/lib/DirectEditing/GraphicsCreator.php new file mode 100644 index 0000000000..479126faf3 --- /dev/null +++ b/lib/DirectEditing/GraphicsCreator.php @@ -0,0 +1,55 @@ + + * + * @author Raul Ferreira Fuentes + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Richdocuments\DirectEditing; + +use OCP\DirectEditing\ACreateEmpty; +use OCP\IL10N; + +class GraphicsCreator extends ACreateEmpty { + + /** + * @var IL10N + */ + private $l10n; + + public function __construct(IL10N $l10n) { + $this->l10n = $l10n; + } + + public function getId(): string { + return 'richdocuments_graphics'; + } + + public function getName(): string { + return $this->l10n->t('diagram'); + } + + public function getExtension(): string { + return 'odg'; + } + + public function getMimetype(): string { + return 'application/vnd.oasis.opendocument.graphics'; + } +} diff --git a/lib/DirectEditing/PresentationCreator.php b/lib/DirectEditing/PresentationCreator.php new file mode 100644 index 0000000000..3df24ccdec --- /dev/null +++ b/lib/DirectEditing/PresentationCreator.php @@ -0,0 +1,59 @@ + + * + * @author Raul Ferreira Fuentes + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Richdocuments\DirectEditing; + +use OCA\Richdocuments\AppInfo\Application; +use OCP\DirectEditing\ACreateEmpty; +use OCP\IConfig; +use OCP\IL10N; + +class PresentationCreator extends ACreateEmpty { + + /** @var IL10N */ + private $l10n; + /** @var IConfig */ + private $config; + + public function __construct(IL10N $l10n, IConfig $config) { + $this->l10n = $l10n; + $this->config = $config; + } + + public function getId(): string { + return 'richdocuments_presentation'; + } + + public function getName(): string { + return $this->l10n->t('presentation'); + } + + public function getExtension(): string { + $useOoxml = $this->config->getAppValue(Application::APPNAME, 'doc_format', '') === 'ooxml'; + return $useOoxml ? 'pptx' : 'odp'; + } + + public function getMimetype(): string { + return 'application/vnd.oasis.opendocument.presentation'; + } +} diff --git a/lib/DirectEditing/SpreadsheetCreator.php b/lib/DirectEditing/SpreadsheetCreator.php new file mode 100644 index 0000000000..9a3daefeac --- /dev/null +++ b/lib/DirectEditing/SpreadsheetCreator.php @@ -0,0 +1,59 @@ + + * + * @author Raul Ferreira Fuentes + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Richdocuments\DirectEditing; + +use OCA\Richdocuments\AppInfo\Application; +use OCP\DirectEditing\ACreateEmpty; +use OCP\IConfig; +use OCP\IL10N; + +class SpreadsheetCreator extends ACreateEmpty { + + /** @var IL10N */ + private $l10n; + /** @var IConfig */ + private $config; + + public function __construct(IL10N $l10n, IConfig $config) { + $this->l10n = $l10n; + $this->config = $config; + } + + public function getId(): string { + return 'richdocuments_spreadsheet'; + } + + public function getName(): string { + return $this->l10n->t('spreadsheet'); + } + + public function getExtension(): string { + $useOoxml = $this->config->getAppValue(Application::APPNAME, 'doc_format', '') === 'ooxml'; + return $useOoxml ? 'xlsx' : 'ods'; + } + + public function getMimetype(): string { + return 'application/vnd.oasis.opendocument.spreadsheet'; + } +} diff --git a/lib/DirectEditing/TextCreator.php b/lib/DirectEditing/TextCreator.php new file mode 100644 index 0000000000..1764df0eef --- /dev/null +++ b/lib/DirectEditing/TextCreator.php @@ -0,0 +1,60 @@ + + * + * @author Raul Ferreira Fuentes + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\Richdocuments\DirectEditing; + +use OCA\Richdocuments\AppInfo\Application; +use OCP\DirectEditing\ACreateEmpty; +use OCP\IConfig; +use OCP\IL10N; + +class TextCreator extends ACreateEmpty { + + /** @var IL10N */ + private $l10n; + /** @var IConfig */ + private $config; + + public function __construct(IL10N $l10n, IConfig $config) { + $this->l10n = $l10n; + $this->config = $config; + } + + public function getId(): string { + return 'richdocuments_text'; + } + + public function getName(): string { + return $this->l10n->t('document'); + } + + public function getExtension(): string { + $useOoxml = $this->config->getAppValue(Application::APPNAME, 'doc_format', '') === 'ooxml'; + return $useOoxml ? 'docx' : 'odt'; + } + + public function getMimetype(): string { + return 'application/vnd.oasis.opendocument.text'; + } +} diff --git a/lib/Listener/RegisterDirectEditorEventListener.php b/lib/Listener/RegisterDirectEditorEventListener.php new file mode 100644 index 0000000000..8690bfe8b0 --- /dev/null +++ b/lib/Listener/RegisterDirectEditorEventListener.php @@ -0,0 +1,48 @@ + + * + * @author Raul Ferreira Fuentes + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Richdocuments\Listener; + +use OCA\Richdocuments\DirectEditing\DirectEditor; +use OCP\DirectEditing\RegisterDirectEditorEvent; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; + +/** @implements IEventListener */ +class RegisterDirectEditorEventListener implements IEventListener { + /** @var DirectEditor */ + protected $editor; + + public function __construct(DirectEditor $editor) { + $this->editor = $editor; + } + + public function handle(Event $event): void { + if (!$event instanceof RegisterDirectEditorEvent) { + return; + } + $event->register($this->editor); + } +}