From 0948ed5520dd13a22256c3fdb66b66f93d06960d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Wed, 24 Feb 2021 16:53:03 +0100 Subject: [PATCH 1/6] Use FileCreatedFromTemplateEvent to inject the already existing empty template files for Collabora MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl Cleanup template loading Signed-off-by: Julius Härtl Fix template handling Signed-off-by: Julius Härtl --- appinfo/info.xml | 3 +- emptyTemplates/odttemplate.odt | Bin 642 -> 0 bytes .../{docxtemplate.docx => template.docx} | Bin .../{odgtemplate.otg => template.odg} | Bin .../{pptxtemplate.pptx => template.pptx} | Bin .../{xlsxtemplate.xlsx => template.xlsx} | Bin lib/AppInfo/Application.php | 3 + lib/Backgroundjobs/Cleanup.php | 49 ++++++ lib/Controller/DocumentController.php | 11 +- .../FileCreatedFromTemplateListener.php | 71 ++++++++ .../Version50200Date20211220212457.php | 51 ++++++ lib/Template/CollaboraTemplateProvider.php | 4 - lib/TemplateManager.php | 151 +++++++++++++----- 13 files changed, 299 insertions(+), 44 deletions(-) delete mode 100644 emptyTemplates/odttemplate.odt rename emptyTemplates/{docxtemplate.docx => template.docx} (100%) rename emptyTemplates/{odgtemplate.otg => template.odg} (100%) rename emptyTemplates/{pptxtemplate.pptx => template.pptx} (100%) rename emptyTemplates/{xlsxtemplate.xlsx => template.xlsx} (100%) create mode 100644 lib/Backgroundjobs/Cleanup.php create mode 100644 lib/Listener/FileCreatedFromTemplateListener.php create mode 100644 lib/Migration/Version50200Date20211220212457.php diff --git a/appinfo/info.xml b/appinfo/info.xml index 465480a701..23bfd2b0c4 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -6,7 +6,7 @@ - 5.0.1 + 5.0.2-dev.1 agpl Collabora Productivity based on work of Frank Karlitschek, Victor Dubiniuk @@ -31,6 +31,7 @@ You can also edit your documents off-line with the Collabora Office app from the OCA\Richdocuments\Backgroundjobs\ObtainCapabilities + OCA\Richdocuments\Backgroundjobs\Cleanup OCA\Richdocuments\Command\ActivateConfig diff --git a/emptyTemplates/odttemplate.odt b/emptyTemplates/odttemplate.odt deleted file mode 100644 index d2a8dc274c6c4476648f4fafe5771789eecee606..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 642 zcmWIWW@Zs#0D;fa^4@XBjCj<6Y!K!E;@r&K)RM}A)Wm{_4Ew*FDoa$J37nJBODAGsMOH%#7ch)%NJ zCOUh(V0+0-e%6KZvu}e(^m;*QDF%f6LD^o8t54)*pE{ zFKxMbeD=P5m)9aZF~LtLFe=G0qaNt^$3V;t#L4-2B_QttogUkNk?XJmkL&&4qKn_J zyPf^wkGQxpN0yiH!oR;cqg}s=fL(w_QXn#nwQz@su|0K zSi4TEEa2D^xHHIL*Tc&CGi6crUIqQLPbIB)&EQqDPregisterTemplateProvider(CollaboraTemplateProvider::class); $context->registerCapability(Capabilities::class); $context->registerMiddleWare(WOPIMiddleware::class); + $context->registerEventListener(FileCreatedFromTemplateEvent::class, FileCreatedFromTemplateListener::class); } public function boot(IBootContext $context): void { diff --git a/lib/Backgroundjobs/Cleanup.php b/lib/Backgroundjobs/Cleanup.php new file mode 100644 index 0000000000..e5adb55acb --- /dev/null +++ b/lib/Backgroundjobs/Cleanup.php @@ -0,0 +1,49 @@ + + * + * @author Roeland Jago Douma + * + * @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\Backgroundjobs; + +use OC\BackgroundJob\TimedJob; +use OCA\Richdocuments\Service\CapabilitiesService; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; + +class Cleanup extends TimedJob { + + /** @var IDBConnection */ + private $db; + + public function __construct(IDBConnection $db) { + $this->db = $db; + + $this->setInterval(60*60); + } + + protected function run($argument) { + // Expire template mappings for file creation + $query = $this->db->getQueryBuilder(); + $query->delete('richdocuments_template') + ->where($query->expr()->lte('timestamp', $query->createNamedParameter(time() - 60, IQueryBuilder::PARAM_INT))); + $query->executeStatement(); + } +} diff --git a/lib/Controller/DocumentController.php b/lib/Controller/DocumentController.php index 9f1f7cec1c..8e1932a20b 100644 --- a/lib/Controller/DocumentController.php +++ b/lib/Controller/DocumentController.php @@ -11,6 +11,7 @@ namespace OCA\Richdocuments\Controller; +use OCA\Richdocuments\AppInfo\Application; use OCA\Richdocuments\Events\BeforeFederationRedirectEvent; use OCA\Richdocuments\Service\FederationService; use OCA\Richdocuments\Service\InitialStateService; @@ -210,7 +211,14 @@ public function index($fileId, $path = null) { return $response; } - list($urlSrc, $token, $wopi) = $this->tokenManager->getToken($item->getId()); + $templateFile = $this->templateManager->getTemplateSource($item->getId()); + if ($templateFile) { + list($urlSrc, $wopi) = $this->tokenManager->getTokenForTemplate($templateFile, $this->uid, $item->getId()); + $token = $wopi->getToken(); + } else { + list($urlSrc, $token, $wopi) = $this->tokenManager->getToken($item->getId()); + } + $params = [ 'permissions' => $item->getPermissions(), 'title' => $item->getName(), @@ -575,6 +583,7 @@ public function create($mimetype, } if (!$content){ + // FIXME: see if this is used, $content = file_get_contents(dirname(dirname(__DIR__)) . self::ODT_TEMPLATE_PATH); } diff --git a/lib/Listener/FileCreatedFromTemplateListener.php b/lib/Listener/FileCreatedFromTemplateListener.php new file mode 100644 index 0000000000..6cc4d472bc --- /dev/null +++ b/lib/Listener/FileCreatedFromTemplateListener.php @@ -0,0 +1,71 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +declare(strict_types=1); + + +namespace OCA\Richdocuments\Listener; + + +use OCA\Richdocuments\AppInfo\Application; +use OCA\Richdocuments\TemplateManager; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; +use OCP\Files\Template\FileCreatedFromTemplateEvent; +use OCP\IConfig; + +class FileCreatedFromTemplateListener implements IEventListener { + + /** @var TemplateManager */ + private $templateManager; + + public function __construct( + TemplateManager $templateManager + ) { + $this->templateManager = $templateManager; + } + + public function handle(Event $event): void { + if (!($event instanceof FileCreatedFromTemplateEvent)) { + return; + } + + $templateFile = $event->getTemplate(); + + // Empty template + if ($templateFile === null) { + $event->getTarget()->putContent($this->templateManager->getEmptyFileContent($event->getTarget()->getExtension())); + return; + } + + if ($this->templateManager->isSupportedTemplateSource($templateFile->getExtension())) { + // Only use TemplateSource if supported filetype + $this->templateManager->setTemplateSource($event->getTarget()->getId(), $templateFile->getId()); + } + + // Avoid having the mimetype of the source file set + $event->getTarget()->getStorage()->getCache()->update($event->getTarget()->getId(), [ + 'mimetype' => $event->getTarget()->getMimeType() + ]); + } +} diff --git a/lib/Migration/Version50200Date20211220212457.php b/lib/Migration/Version50200Date20211220212457.php new file mode 100644 index 0000000000..5eb408c12f --- /dev/null +++ b/lib/Migration/Version50200Date20211220212457.php @@ -0,0 +1,51 @@ +hasTable('richdocuments_template')) { + $table = $schema->createTable('richdocuments_template'); + $table->addColumn('id', 'bigint', [ + 'autoincrement' => true, + 'notnull' => true, + 'length' => 20, + 'unsigned' => true, + ]); + $table->addColumn('userid', 'string', [ + 'notnull' => false, + 'length' => 64, + ]); + $table->addColumn('fileid', 'bigint', [ + 'notnull' => true, + 'length' => 20, + ]); + $table->addColumn('templateid', 'bigint', [ + 'notnull' => true, + 'length' => 20, + ]); + $table->addColumn('timestamp', 'bigint', [ + 'notnull' => true, + 'length' => 20, + 'unsigned' => true, + ]); + $table->setPrimaryKey(['id']); + $table->addUniqueIndex(['userid', 'fileid'], 'rd_t_user_file'); + } + + return $schema; + } +} diff --git a/lib/Template/CollaboraTemplateProvider.php b/lib/Template/CollaboraTemplateProvider.php index 409ba70ca0..e7abad9dc6 100644 --- a/lib/Template/CollaboraTemplateProvider.php +++ b/lib/Template/CollaboraTemplateProvider.php @@ -91,8 +91,4 @@ private function isSameUserTemplateFolder(): bool { public function getCustomTemplate(string $template): File { return $this->templateManager->get((int)$template); } - - public function createFromTemplate(File $template, File $target): void { - // TODO: Implement createFromTemplate() method. - } } diff --git a/lib/TemplateManager.php b/lib/TemplateManager.php index 2974a9c65e..1f4d14991e 100644 --- a/lib/TemplateManager.php +++ b/lib/TemplateManager.php @@ -24,6 +24,8 @@ namespace OCA\Richdocuments; +use OCA\Richdocuments\AppInfo\Application; +use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Files\File; use OCP\Files\Folder; use OCP\Files\IAppData; @@ -31,16 +33,14 @@ use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\IConfig; +use OCP\IDBConnection; use OCP\IL10N; -use OCP\IPreview; use OCP\IURLGenerator; -use OC\Files\AppData\Factory; +use Psr\Log\LoggerInterface; +use Throwable; class TemplateManager { - /** @var string */ - protected $appName; - /** @var string */ protected $userId; @@ -56,6 +56,15 @@ class TemplateManager { /** @var IL10N */ private $l; + /** @var IDBConnection */ + private $db; + + /** @var IAppData */ + private $appData; + + /** @var LoggerInterface */ + private $logger; + /** Accepted templates mime types */ const MIMES_DOCUMENTS = [ 'application/vnd.oasis.opendocument.text-template', @@ -97,39 +106,27 @@ class TemplateManager { 'presentation' => 'pptx', ]; - /** - * Template manager - * - * @param string $appName - * @param string $userId - * @param IConfig $config - * @param Factory $appDataFactory - * @param IURLGenerator $urlGenerator - * @param IRootFolder $rootFolder - * @param IL10N $l - * @throws \OCP\Files\NotPermittedException - */ - public function __construct($appName, - $userId, - IConfig $config, - IAppData $appData, - IURLGenerator $urlGenerator, - IRootFolder $rootFolder, - IL10N $l) { - $this->appName = $appName; - $this->userId = $userId; - $this->config = $config; - $this->rootFolder = $rootFolder; - $this->urlGenerator = $urlGenerator; - - + public function __construct( + $userId, + IConfig $config, + IAppData $appData, + IURLGenerator $urlGenerator, + IRootFolder $rootFolder, + IL10N $l, + IDBConnection $connection, + LoggerInterface $logger + ) { + $this->userId = $userId; + $this->config = $config; + $this->rootFolder = $rootFolder; + $this->urlGenerator = $urlGenerator; + $this->db = $connection; + $this->logger = $logger; $this->appData = $appData; - $this->createAppDataFolders(); - $this->l = $l; } - private function createAppDataFolders() { + private function ensureAppDataFolders() { /* * Init the appdata folder * We need an actual folder for the fileid and previews. @@ -200,7 +197,7 @@ private function filterTemplates($templates, $type = null) { }); } - private function getEmpty($type = null) { + public function getEmpty($type = null) { $folder = $this->getEmptyTemplateDir(); $templateFiles = $folder->getDirectoryListing(); @@ -228,6 +225,7 @@ private function getEmpty($type = null) { * Remove empty_templates in appdata and recreate it from the apps templates */ public function updateEmptyTemplates() { + $this->ensureAppDataFolders(); try { $folder = $this->getEmptyTemplateDir(); $folder->delete(); @@ -393,7 +391,7 @@ public function getUserTemplateDir() { } // has the user manually set a directory as the default template dir ? - $templateDirPath = $this->config->getUserValue($this->userId, $this->appName, 'templateFolder', false); + $templateDirPath = $this->config->getUserValue($this->userId, Application::APPNAME, 'templateFolder', false); $userFolder = $this->rootFolder->getUserFolder($this->userId); if ($templateDirPath !== false) { @@ -418,6 +416,7 @@ public function getUserTemplateDir() { * @return Folder */ private function getSystemTemplateDir() { + $this->ensureAppDataFolders(); $path = 'appdata_' . $this->config->getSystemValue('instanceid', null) . '/richdocuments/templates'; return $this->rootFolder->get($path); } @@ -426,6 +425,7 @@ private function getSystemTemplateDir() { * @return Folder */ private function getEmptyTemplateDir() { + $this->ensureAppDataFolders(); $path = 'appdata_' . $this->config->getSystemValue('instanceid', null) . '/richdocuments/empty_templates'; return $this->rootFolder->get($path); } @@ -437,7 +437,7 @@ private function getEmptyTemplateDir() { * @return array */ public function formatNodeReturn(File $template) { - $ooxml = $this->config->getAppValue($this->appName, 'doc_format', '') === 'ooxml'; + $ooxml = $this->config->getAppValue(Application::APPNAME, 'doc_format', '') === 'ooxml'; $documentType = $this->flipTypes()[$template->getMimeType()]; return [ 'id' => $template->getId(), @@ -466,7 +466,7 @@ public function isTemplate($fileId) { } public function formatEmpty(File $template) { - $ooxml = $this->config->getAppValue($this->appName, 'doc_format', '') === 'ooxml'; + $ooxml = $this->config->getAppValue(Application::APPNAME, 'doc_format', '') === 'ooxml'; $documentType = $this->flipTypes()[$template->getMimeType()]; return [ 'id' => $template->getId(), @@ -490,4 +490,79 @@ public function isValidTemplateMime($mime, $type = null) { return true; } + + /** + * Return default content for empty files of a given filename by file extension + */ + public function getEmptyFileContent(string $extension): string { + $supportedExtensions = ['odt', 'ods', 'odp', 'odg', 'docx', 'xlsx', 'pptx']; + $emptyPath = __DIR__ . '/../emptyTemplates/template.' . $extension; + + if (in_array($extension, $supportedExtensions, true) && file_exists($emptyPath)) { + return file_get_contents($emptyPath); + } + + return ''; + } + + public function isSupportedTemplateSource(string $extension): bool { + $supportedExtensions = ['ott', 'otg', 'otp', 'ots']; + return in_array($extension, $supportedExtensions, true); + } + + public function setTemplateSource(int $fileId, int $templateId): void { + try { + $query = $this->db->getQueryBuilder(); + $query->insert('richdocuments_template') + ->values([ + 'userid' => $query->createNamedParameter($this->userId), + 'fileid' => $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT), + 'templateid' => $query->createNamedParameter($templateId, IQueryBuilder::PARAM_INT), + 'timestamp' => $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT) + ]); + $query->executeStatement(); + } catch (Throwable $e) { + $this->logger->warning('Could not store template source', ['exception' => $e]); + // Ignore failure and proceed with empty template + } + } + + public function getTemplateSource(int $fileId): ?File { + $templateId = 0; + try { + $query = $this->db->getQueryBuilder(); + $query->select('templateid') + ->from('richdocuments_template') + ->where($query->expr()->eq('userid', $query->createNamedParameter($this->userId))) + ->andWhere($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))); + $result = $query->executeQuery(); + $templateId = (int)$result->fetchOne(); + + $query->delete('richdocuments_template') + ->where($query->expr()->eq('userid', $query->createNamedParameter($this->userId))) + ->andWhere($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))); + $query->executeStatement(); + } catch (Throwable $e) { + // Ignore failure and proceed with empty template + $this->logger->warning('Could not retrieve template source', ['exception' => $e]); + return null; + } + + if ($templateId !== 0) { + try { + $template = $this->get($templateId); + } catch (NotFoundException $e) { + $userFolder = $this->rootFolder->getUserFolder($this->userId); + try { + $template = $userFolder->getById($templateId); + } catch (NotFoundException $e) { + $this->logger->warning('Could not retrieve template source file', ['exception' => $e]); + return null; + } + } + return $template; + } + + return null; + } } From 08923968bd99fd2c8d43164618b69d3d37634572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Fri, 15 Oct 2021 12:30:08 +0200 Subject: [PATCH 2/6] Remove unneeded debug output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- lib/AppInfo/Application.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index a8af2239fe..67a0800009 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -186,9 +186,7 @@ public function registerProvider() { return $container->query(OOXML::class); }); - // \OC::$server->getLogger()->debug('==== Richdocuments Application registerProvider: calling manager registerProvider:'); $previewManager->registerProvider('/application\/vnd.oasis.opendocument.*/', function() use ($container) { - // \OC::$server->getLogger()->debug('==== Richdocuments Application registerProvider lambda. OpenDocument::class=' . OpenDocument::class); return $container->query(OpenDocument::class); }); From 7842c45a6d3fdbc8e505ec13440d710236d63abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Tue, 21 Dec 2021 10:46:25 +0100 Subject: [PATCH 3/6] Update psalm checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- composer.json | 4 +- composer.lock | 503 +++++++++++++++--- .../FileCreatedFromTemplateListener.php | 1 + tests/psalm-baseline.xml | 51 +- 4 files changed, 450 insertions(+), 109 deletions(-) diff --git a/composer.json b/composer.json index c49b032d0e..930de69d15 100644 --- a/composer.json +++ b/composer.json @@ -1,9 +1,11 @@ { "name": "nextcloud/richdocuments", "type": "project", + "minimum-stability": "dev", + "prefer-stable" : true, "require-dev": { "roave/security-advisories": "dev-master", - "christophwurst/nextcloud": "^21.0", + "christophwurst/nextcloud": "dev-master", "jakub-onderka/php-parallel-lint": "^1.0.0", "psalm/phar": "^4.7" }, diff --git a/composer.lock b/composer.lock index 979e2aeff3..0fd411155c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,30 +4,34 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "90f8328b3e89d8d8cafc03dfa5099c14", + "content-hash": "e2bb8c059ec5db70289266d1469aea82", "packages": [], "packages-dev": [ { "name": "christophwurst/nextcloud", - "version": "v21.0.0", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/ChristophWurst/nextcloud_composer.git", - "reference": "41e1476b4aed5bce7371895054049eca353729c5" + "reference": "e59cb0a896ed593de359673a7d85f4d02406e2d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ChristophWurst/nextcloud_composer/zipball/41e1476b4aed5bce7371895054049eca353729c5", - "reference": "41e1476b4aed5bce7371895054049eca353729c5", + "url": "https://api.github.com/repos/ChristophWurst/nextcloud_composer/zipball/e59cb0a896ed593de359673a7d85f4d02406e2d9", + "reference": "e59cb0a896ed593de359673a7d85f4d02406e2d9", "shasum": "" }, "require": { - "php": "^7.3 || ~8.0.0" + "php": "^7.3 || ~8.0.0", + "psr/container": "^1.0", + "psr/event-dispatcher": "^1.0", + "psr/log": "^1.1" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-master": "21.0.0-dev" + "dev-master": "24.0.0-dev" } }, "notification-url": "https://packagist.org/downloads/", @@ -43,9 +47,9 @@ "description": "Composer package containing Nextcloud's public API (classes, interfaces)", "support": { "issues": "https://github.com/ChristophWurst/nextcloud_composer/issues", - "source": "https://github.com/ChristophWurst/nextcloud_composer/tree/v21.0.0" + "source": "https://github.com/ChristophWurst/nextcloud_composer/tree/master" }, - "time": "2021-03-01T08:42:25+00:00" + "time": "2021-12-21T01:14:58+00:00" }, { "name": "jakub-onderka/php-parallel-lint", @@ -93,6 +97,11 @@ ], "description": "This tool check syntax of PHP files about 20x faster than serial check.", "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint", + "support": { + "issues": "https://github.com/JakubOnderka/PHP-Parallel-Lint/issues", + "source": "https://github.com/JakubOnderka/PHP-Parallel-Lint/tree/master" + }, + "abandoned": "php-parallel-lint/php-parallel-lint", "time": "2018-02-24T15:31:20+00:00" }, { @@ -130,180 +139,525 @@ }, "time": "2021-11-23T23:59:04+00:00" }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, { "name": "roave/security-advisories", "version": "dev-master", "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "a53a6f855cbff7edb078f87c72bb808c89443a00" + "reference": "fff53639bf1fa25f311c3e54932ac8c827f9a343" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/a53a6f855cbff7edb078f87c72bb808c89443a00", - "reference": "a53a6f855cbff7edb078f87c72bb808c89443a00", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/fff53639bf1fa25f311c3e54932ac8c827f9a343", + "reference": "fff53639bf1fa25f311c3e54932ac8c827f9a343", "shasum": "" }, "conflict": { "3f/pygmentize": "<1.2", "adodb/adodb-php": "<5.20.12", + "akaunting/akaunting": "<2.1.13", "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", + "amazing/media2click": ">=1,<1.3.3", "amphp/artax": "<1.0.6|>=2,<2.0.6", "amphp/http": "<1.0.1", + "amphp/http-client": ">=4,<4.4", "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6", + "area17/twill": "<1.2.5|>=2,<2.5.3", "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", "aws/aws-sdk-php": ">=3,<3.2.1", + "bagisto/bagisto": "<0.1.5", + "barrelstrength/sprout-base-email": "<1.2.7", + "barrelstrength/sprout-forms": "<3.9", + "baserproject/basercms": "<4.5.4", + "billz/raspap-webgui": "<=2.6.6", + "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", + "bolt/bolt": "<3.7.2", + "bolt/core": "<4.1.13", "brightlocal/phpwhois": "<=4.2.5", + "buddypress/buddypress": "<7.2.1", "bugsnag/bugsnag-laravel": ">=2,<2.0.2", + "cachethq/cachet": "<2.5.1", "cakephp/cakephp": ">=1.3,<1.3.18|>=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.5.18|>=3.6,<3.6.15|>=3.7,<3.7.7", + "cardgate/magento2": "<2.0.33", "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", "cartalyst/sentry": "<=2.1.6", + "catfan/medoo": "<1.7.5", + "centreon/centreon": "<20.10.7", + "cesnet/simplesamlphp-module-proxystatistics": "<3.1", + "codeception/codeception": "<3.1.3|>=4,<4.1.22", "codeigniter/framework": "<=3.0.6", - "composer/composer": "<=1-alpha.11", + "codiad/codiad": "<=2.8.4", + "composer/composer": "<1.10.23|>=2-alpha.1,<2.1.9", + "concrete5/concrete5": "<8.5.5", + "concrete5/core": "<8.5.7", "contao-components/mediaelement": ">=2.14.2,<2.21.1", "contao/core": ">=2,<3.5.39", - "contao/core-bundle": ">=4,<4.4.39|>=4.5,<4.7.5", + "contao/core-bundle": ">=4,<4.4.56|>=4.5,<4.9.18|>=4.10,<4.11.7|= 4.10.0", "contao/listing-bundle": ">=4,<4.4.8", - "contao/newsletter-bundle": ">=4,<4.1", + "craftcms/cms": "<3.7.14", + "croogo/croogo": "<3.0.7", + "datadog/dd-trace": ">=0.30,<0.30.2", "david-garcia/phpwhois": "<=4.3.1", + "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1", + "directmailteam/direct-mail": "<5.2.4", "doctrine/annotations": ">=1,<1.2.7", "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", - "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2|>=3,<3.1.4", "doctrine/doctrine-bundle": "<1.5.2", "doctrine/doctrine-module": "<=0.7.1", "doctrine/mongodb-odm": ">=1,<1.0.2", "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", - "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1", + "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", + "dolibarr/dolibarr": "<14|>= 3.3.beta1, < 13.0.2", "dompdf/dompdf": ">=0.6,<0.6.2", - "drupal/core": ">=7,<7.67|>=8,<8.6.16|>=8.7,<8.7.1", - "drupal/drupal": ">=7,<7.67|>=8,<8.6.16|>=8.7,<8.7.1", + "drupal/core": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", + "drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", + "dweeves/magmi": "<=0.7.24", + "ecodev/newsletter": "<=4", + "elgg/elgg": "<3.3.23|>=4,<4.0.5", + "endroid/qr-code-bundle": "<3.4.2", + "enshrined/svg-sanitize": "<0.13.1", "erusev/parsedown": "<1.7.2", - "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.4", - "ezsystems/ezpublish-kernel": ">=5.3,<5.3.12.1|>=5.4,<5.4.13.1|>=6,<6.7.9.1|>=6.8,<6.13.5.1|>=7,<7.2.4.1|>=7.3,<7.3.2.1", - "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.6|>=5.4,<5.4.12.3|>=2011,<2017.12.4.3|>=2018.6,<2018.6.1.4|>=2018.9,<2018.9.1.3", + "ether/logs": "<3.0.4", + "ezsystems/demobundle": ">=5.4,<5.4.6.1", + "ezsystems/ez-support-tools": ">=2.2,<2.2.3", + "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1", + "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1", + "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<=1.5.25", + "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", + "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<=1.3.1", + "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", + "ezsystems/ezplatform-richtext": ">=2.3,<=2.3.7", + "ezsystems/ezplatform-user": ">=1,<1.0.1", + "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<=7.5.15.1", + "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.3.5.1", + "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", "ezsystems/repository-forms": ">=2.3,<2.3.2.1", "ezyang/htmlpurifier": "<4.1.1", + "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", + "feehi/cms": "<=2.1.1", + "feehi/feehicms": "<=0.1.3", "firebase/php-jwt": "<2", + "flarum/core": ">=1,<=1.0.1", + "flarum/sticky": ">=0.1-beta.14,<=0.1-beta.15", + "flarum/tags": "<=0.1-beta.13", + "fluidtypo3/vhs": "<5.1.1", "fooman/tcpdf": "<6.2.22", + "forkcms/forkcms": "<=5.9.2", "fossar/tcpdf-parser": "<6.2.22", + "francoisjacquet/rosariosis": "<8.1.1", + "friendsofsymfony/oauth2-php": "<1.3", "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", + "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", + "froala/wysiwyg-editor": "<3.2.7", "fuel/core": "<1.8.1", + "getgrav/grav": "<=1.7.24", + "getkirby/cms": "<3.5.8", + "getkirby/panel": "<2.5.14", + "gilacms/gila": "<=1.11.4", + "globalpayments/php-sdk": "<2", + "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", "gree/jose": "<=2.2", "gregwar/rst": "<1.0.3", + "grumpydictator/firefly-iii": "<5.6.5", "guzzlehttp/guzzle": ">=4-rc.2,<4.2.4|>=5,<5.3.1|>=6,<6.2.1", + "helloxz/imgurl": "<=2.31", + "hjue/justwriting": "<=1", + "hov/jobfair": "<1.0.13|>=2,<2.0.2", + "ibexa/post-install": "<=1.0.4", + "icecoder/icecoder": "<=8", "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", - "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.42|>=5.6,<5.6.30", - "illuminate/database": ">=4,<4.0.99|>=4.1,<4.1.29", + "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.99999|>=4.2,<=4.2.99999|>=5,<=5.0.99999|>=5.1,<=5.1.99999|>=5.2,<=5.2.99999|>=5.3,<=5.3.99999|>=5.4,<=5.4.99999|>=5.5,<=5.5.49|>=5.6,<=5.6.99999|>=5.7,<=5.7.99999|>=5.8,<=5.8.99999|>=6,<6.18.31|>=7,<7.22.4", + "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", + "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", + "impresscms/impresscms": "<=1.4.2", + "in2code/femanager": "<5.5.1|>=6,<6.3.1", + "intelliants/subrion": "<=4.2.1", "ivankristianto/phpwhois": "<=4.3", - "james-heinrich/getid3": "<1.9.9", + "jackalope/jackalope-doctrine-dbal": "<1.7.4", + "james-heinrich/getid3": "<1.9.21", + "joomla/archive": "<1.1.10", "joomla/session": "<1.3.1", "jsmitty12/phpwhois": "<5.1", "kazist/phpwhois": "<=4.2.6", + "kevinpapst/kimai2": "<1.16.7", + "kitodo/presentation": "<3.1.2", + "klaviyo/magento2-extension": ">=1,<3", "kreait/firebase-php": ">=3.2,<3.8.1", "la-haute-societe/tcpdf": "<6.2.22", - "laravel/framework": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.42|>=5.6,<5.6.30", + "laminas/laminas-http": "<2.14.2", + "laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75", "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", + "lavalite/cms": "<=5.8", + "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", "league/commonmark": "<0.18.3", - "magento/magento1ce": "<1.9.4.1", - "magento/magento1ee": ">=1.9,<1.14.4.1", - "magento/product-community-edition": ">=2,<2.2.8|>=2.3,<2.3.1", + "league/flysystem": "<1.1.4|>=2,<2.1.1", + "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", + "librenms/librenms": "<=21.11", + "limesurvey/limesurvey": "<3.27.19", + "livewire/livewire": ">2.2.4,<2.2.6", + "lms/routes": "<2.1.1", + "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", + "magento/community-edition": ">=2,<2.2.10|>=2.3,<2.3.3", + "magento/magento1ce": "<1.9.4.3", + "magento/magento1ee": ">=1,<1.14.4.3", + "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", + "marcwillmann/turn": "<0.3.3", + "mautic/core": "<4|= 2.13.1", + "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35", + "microweber/microweber": "<1.2.8", + "miniorange/miniorange-saml": "<1.4.3", + "mittwald/typo3_forum": "<1.2.1", + "modx/revolution": "<2.8", "monolog/monolog": ">=1.8,<1.12", + "moodle/moodle": "<3.5.17|>=3.7,<3.7.9|>=3.8,<3.8.8|>=3.9,<3.9.5|>=3.10-beta,<3.10.2", "namshi/jose": "<2.2", + "neoan3-apps/template": "<1.1.1", + "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3", + "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.9.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", + "neos/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", + "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", + "nilsteampassnet/teampass": "<=2.1.27.36", + "nukeviet/nukeviet": "<4.3.4", + "nystudio107/craft-seomatic": "<3.3", + "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", + "october/backend": "<1.1.2", + "october/cms": "= 1.1.1|= 1.0.471|= 1.0.469|>=1.0.319,<1.0.469", + "october/october": ">=1.0.319,<1.0.466|>=2.1,<2.1.12", + "october/rain": "<1.0.472|>=1.1,<1.1.2", + "october/system": "<1.0.472|>=1.1.1,<1.1.5|>=2.1,<2.1.12", "onelogin/php-saml": "<2.10.4", + "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", + "opencart/opencart": "<=3.0.3.2", "openid/php-openid": "<2.3", - "oro/crm": ">=1.7,<1.7.4", + "openmage/magento-lts": "<19.4.15|>=20,<20.0.13", + "orchid/platform": ">=9,<9.4.4", + "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", "oro/platform": ">=1.7,<1.7.4", "padraic/humbug_get_contents": "<1.1.2", "pagarme/pagarme-php": ">=0,<3", + "pagekit/pagekit": "<=1.0.18", "paragonie/random_compat": "<2", + "passbolt/passbolt_api": "<2.11", "paypal/merchant-sdk-php": "<3.12", - "pear/archive_tar": "<1.4.4", - "phpmailer/phpmailer": ">=5,<5.2.27|>=6,<6.0.6", - "phpoffice/phpexcel": "<=1.8.1", - "phpoffice/phpspreadsheet": "<=1.5", + "pear/archive_tar": "<1.4.14", + "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", + "personnummer/personnummer": "<3.0.2", + "phanan/koel": "<5.1.4", + "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", + "phpmailer/phpmailer": "<6.5", + "phpmussel/phpmussel": ">=1,<1.6", + "phpmyadmin/phpmyadmin": "<4.9.6|>=5,<5.0.3", + "phpoffice/phpexcel": "<1.8.2", + "phpoffice/phpspreadsheet": "<1.16", + "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.7", + "phpservermon/phpservermon": "<=3.5.2", "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", "phpwhois/phpwhois": "<=4.2.5", "phpxmlrpc/extras": "<0.6.1", + "pimcore/pimcore": "<10.2.6", + "pocketmine/pocketmine-mp": "<4.0.3", + "pressbooks/pressbooks": "<5.18", + "prestashop/autoupgrade": ">=4,<4.10.1", + "prestashop/contactform": ">1.0.1,<4.3", + "prestashop/gamification": "<2.3.2", + "prestashop/prestashop": ">=1.7.5,<=1.7.8.1", + "prestashop/productcomments": ">=4,<4.2.1", + "prestashop/ps_emailsubscription": "<2.6.1", + "prestashop/ps_facetedsearch": "<3.4.1", + "prestashop/ps_linklist": "<3.1", + "privatebin/privatebin": "<1.2.2|>=1.3,<1.3.2", "propel/propel": ">=2-alpha.1,<=2-alpha.7", "propel/propel1": ">=1,<=1.7.1", + "pterodactyl/panel": "<1.6.6", "pusher/pusher-php-server": "<2.2.1", - "robrichards/xmlseclibs": ">=1,<3.0.2", + "pwweb/laravel-core": "<=0.3.6-beta", + "rainlab/debugbar-plugin": "<3.1", + "remdex/livehelperchat": "<=3.90", + "rmccue/requests": ">=1.6,<1.8", + "robrichards/xmlseclibs": "<3.0.4", + "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", + "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", "sensiolabs/connect": "<4.2.3", "serluck/phpwhois": "<=4.2.6", - "shopware/shopware": "<5.3.7", - "silverstripe/cms": ">=3,<=3.0.11|>=3.1,<3.1.11", + "shopware/core": "<=6.4.6", + "shopware/platform": "<=6.4.6", + "shopware/production": "<=6.3.5.2", + "shopware/shopware": "<5.7.6", + "showdoc/showdoc": "<=2.9.13", + "silverstripe/admin": "<4.8.1", + "silverstripe/assets": ">=1,<1.4.7|>=1.5,<1.5.2", + "silverstripe/cms": "<4.3.6|>=4.4,<4.4.4", + "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", - "silverstripe/framework": ">=3,<3.6.7|>=3.7,<3.7.3|>=4,<4.4", - "silverstripe/graphql": ">=2,<2.0.5|>=3,<3.1.2", + "silverstripe/framework": "<4.7.4", + "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2", "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4", + "silverstripe/subsites": ">=2,<2.1.1", + "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", "silverstripe/userforms": "<3", "simple-updates/phpwhois": "<=1", "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4", - "simplesamlphp/simplesamlphp": "<1.15.2|>=1.16,<1.16.3", + "simplesamlphp/simplesamlphp": "<1.18.6", "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "simplito/elliptic-php": "<1.0.6", "slim/slim": "<2.6", - "smarty/smarty": "<3.1.33", + "smarty/smarty": "<3.1.39", + "snipe/snipe-it": "<5.3.5", "socalnick/scn-social-auth": "<1.15.2", + "socialiteproviders/steam": "<1.1", "spoonity/tcpdf": "<6.2.22", "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", + "ssddanbrown/bookstack": "<21.11.3", "stormpath/sdk": ">=0,<9.9.99", + "studio-42/elfinder": "<2.1.59", + "subrion/cms": "<=4.2.1", + "sulu/sulu": "= 2.4.0-RC1|<1.6.44|>=2,<2.2.18|>=2.3,<2.3.8", "swiftmailer/swiftmailer": ">=4,<5.4.5", "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", "sylius/grid-bundle": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", - "sylius/sylius": ">=1,<1.1.18|>=1.2,<1.2.17|>=1.3,<1.3.12|>=1.4,<1.4.4", - "symfony/cache": ">=3.1,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "sylius/paypal-plugin": ">=1,<1.2.4|>=1.3,<1.3.1", + "sylius/resource-bundle": "<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", + "sylius/sylius": "<1.6.9|>=1.7,<1.7.9|>=1.8,<1.8.3|>=1.9,<1.9.5", + "symbiote/silverstripe-multivaluefield": ">=3,<3.0.99", + "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", + "symbiote/silverstripe-versionedfiles": "<=2.0.3", + "symfont/process": ">=0,<4", + "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", - "symfony/http-foundation": ">=2,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", - "symfony/http-kernel": ">=2,<2.3.29|>=2.4,<2.5.12|>=2.6,<2.6.8", + "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7", + "symfony/http-kernel": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.4.13|>=5,<5.1.5|>=5.2,<5.3.12", "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", + "symfony/mime": ">=4.3,<4.3.8", "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/polyfill": ">=1,<1.10", "symfony/polyfill-php55": ">=1,<1.10", "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/routing": ">=2,<2.0.19", - "symfony/security": ">=2,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", - "symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", - "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<2.8.37|>=3,<3.3.17|>=3.4,<3.4.7|>=4,<4.0.7", + "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", + "symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11|>=5.3,<5.3.12", + "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", - "symfony/security-guard": ">=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", - "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", - "symfony/serializer": ">=2,<2.0.11", - "symfony/symfony": ">=2,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", + "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8|>=5.3,<5.3.2", + "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", + "symfony/symfony": ">=2,<3.4.49|>=4,<4.4.35|>=5,<5.3.12", "symfony/translation": ">=2,<2.0.17", "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", + "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", + "t3/dce": ">=2.2,<2.6.2", + "t3g/svg-sanitizer": "<1.0.3", "tecnickcom/tcpdf": "<6.2.22", "thelia/backoffice-default-template": ">=2.1,<2.1.2", "thelia/thelia": ">=2.1-beta.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", + "tinymce/tinymce": "<5.10", "titon/framework": ">=0,<9.9.99", + "topthink/framework": "<6.0.9", + "topthink/think": "<=6.0.9", + "topthink/thinkphp": "<=3.2.3", + "tribalsystems/zenario": "<8.8.53370", "truckersmp/phpwhois": "<=4.3.1", "twig/twig": "<1.38|>=2,<2.7", - "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.27|>=9,<9.5.8", - "typo3/cms-core": ">=8,<8.7.27|>=9,<9.5.8", - "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5", - "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4", + "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.19|>=11,<11.5", + "typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", + "typo3/cms-core": ">=6.2,<=6.2.56|>=7,<=7.6.52|>=8,<=8.7.41|>=9,<9.5.29|>=10,<10.4.19|>=11,<11.5", + "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", + "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", + "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", "ua-parser/uap-php": "<3.8", + "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", + "vanilla/safecurl": "<0.9.2", + "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4", + "vrana/adminer": "<4.7.9", "wallabag/tcpdf": "<6.2.22", + "wanglelecc/laracms": "<=1.0.3", + "web-auth/webauthn-framework": ">=3.3,<3.3.4", + "webcoast/deferred-image-processing": "<1.0.2", + "wikimedia/parsoid": "<0.12.2", "willdurand/js-translation-bundle": "<2.1.1", + "wp-cli/wp-cli": "<2.5", + "yetiforce/yetiforce-crm": "<=6.3", + "yidashi/yii2cmf": "<=2", + "yii2mod/yii2-cms": "<1.9.2", "yiisoft/yii": ">=1.1.14,<1.1.15", - "yiisoft/yii2": "<2.0.15", + "yiisoft/yii2": "<2.0.38", "yiisoft/yii2-bootstrap": "<2.0.4", - "yiisoft/yii2-dev": "<2.0.15", + "yiisoft/yii2-dev": "<2.0.43", "yiisoft/yii2-elasticsearch": "<2.0.5", "yiisoft/yii2-gii": "<2.0.4", "yiisoft/yii2-jui": "<2.0.4", "yiisoft/yii2-redis": "<2.0.8", + "yoast-seo-for-typo3/yoast_seo": "<7.2.3", + "yourls/yourls": "<=1.8.2", + "zendesk/zendesk_api_client_php": "<2.2.11", "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", @@ -321,14 +675,15 @@ "zendframework/zend-validator": ">=2.3,<2.3.6", "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", - "zendframework/zendframework": "<2.5.1", + "zendframework/zendframework": "<=3", "zendframework/zendframework1": "<1.12.20", "zendframework/zendopenid": ">=2,<2.0.2", "zendframework/zendxml": ">=1,<1.0.1", "zetacomponents/mail": "<1.8.2", "zf-commons/zfc-user": "<1.2.2", "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", - "zfr/zfr-oauth2-server-module": "<0.1.2" + "zfr/zfr-oauth2-server-module": "<0.1.2", + "zoujingli/thinkadmin": "<6.0.22" }, "type": "metapackage", "notification-url": "https://packagist.org/downloads/", @@ -340,18 +695,38 @@ "name": "Marco Pivetta", "email": "ocramius@gmail.com", "role": "maintainer" + }, + { + "name": "Ilya Tribusean", + "email": "slash3b@gmail.com", + "role": "maintainer" } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2019-06-25T10:37:35+00:00" + "support": { + "issues": "https://github.com/Roave/SecurityAdvisories/issues", + "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" + }, + "funding": [ + { + "url": "https://github.com/Ocramius", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/roave/security-advisories", + "type": "tidelift" + } + ], + "time": "2021-12-17T20:13:17+00:00" } ], "aliases": [], - "minimum-stability": "stable", + "minimum-stability": "dev", "stability-flags": { - "roave/security-advisories": 20 + "roave/security-advisories": 20, + "christophwurst/nextcloud": 20 }, - "prefer-stable": false, + "prefer-stable": true, "prefer-lowest": false, "platform": [], "platform-dev": [], diff --git a/lib/Listener/FileCreatedFromTemplateListener.php b/lib/Listener/FileCreatedFromTemplateListener.php index 6cc4d472bc..161ad39043 100644 --- a/lib/Listener/FileCreatedFromTemplateListener.php +++ b/lib/Listener/FileCreatedFromTemplateListener.php @@ -34,6 +34,7 @@ use OCP\Files\Template\FileCreatedFromTemplateEvent; use OCP\IConfig; +/** @template-implements IEventListener */ class FileCreatedFromTemplateListener implements IEventListener { /** @var TemplateManager */ diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml index 012ff82079..d705ac7aa6 100644 --- a/tests/psalm-baseline.xml +++ b/tests/psalm-baseline.xml @@ -15,20 +15,7 @@ - - $container - $container - $container - $container - $container - $container - $container - $container - $this->getContainer() - $this->getContainer() - $this->getContainer() - $this->getContainer() - $this->getContainer() + MSExcel MSWord OOXML @@ -73,13 +60,6 @@ - - - new TemplateResponse('core', 'error', $params, 'guest') - - - array - $fileId $item->getId() @@ -87,7 +67,7 @@ $item->getId() $node->getId() - + $this->rootFolder $this->rootFolder $this->rootFolder @@ -96,7 +76,6 @@ BeforeFederationRedirectEvent IRootFolder IRootFolder - ShareNotFound $app !== '' @@ -110,13 +89,11 @@ - - + $this->rootFolder $this->rootFolder IRootFolder IRootFolder - ShareNotFound @@ -140,15 +117,12 @@ L10N - - !($node instanceof Node) - L10N - + $this->rootFolder $this->rootFolder $this->rootFolder @@ -162,7 +136,6 @@ $this->rootFolder IRootFolder IRootFolder - ShareNotFound \OC_User @@ -233,12 +206,6 @@ $this->userSession - - - TemplateResponse - string - - @@ -246,28 +213,24 @@ - + + $this->rootFolder $this->rootFolder $this->rootFolder $this->rootFolder IRootFolder IRootFolder - - $this->appData - $this->appData - $node->getId() - + $this->rootFolder $this->rootFolder IRootFolder IRootFolder - ShareNotFound null From d0b6ef883ecb3bbfc7278aa9faad8a20d11f110f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Tue, 21 Dec 2021 13:03:05 +0100 Subject: [PATCH 4/6] Add composer platform config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- composer.json | 5 +++++ composer.lock | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 930de69d15..6ae194dfb1 100644 --- a/composer.json +++ b/composer.json @@ -3,6 +3,11 @@ "type": "project", "minimum-stability": "dev", "prefer-stable" : true, + "config": { + "platform": { + "php": "7.3" + } + }, "require-dev": { "roave/security-advisories": "dev-master", "christophwurst/nextcloud": "dev-master", diff --git a/composer.lock b/composer.lock index 0fd411155c..9a3635fc82 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e2bb8c059ec5db70289266d1469aea82", + "content-hash": "ee36e4939f0d706a6cb294c3acb1b460", "packages": [], "packages-dev": [ { @@ -141,20 +141,20 @@ }, { "name": "psr/container", - "version": "1.1.2", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", "shasum": "" }, "require": { - "php": ">=7.4.0" + "php": ">=7.2.0" }, "type": "library", "autoload": { @@ -183,9 +183,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" + "source": "https://github.com/php-fig/container/tree/1.1.1" }, - "time": "2021-11-05T16:50:12+00:00" + "time": "2021-03-05T17:36:06+00:00" }, { "name": "psr/event-dispatcher", @@ -730,5 +730,8 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], + "platform-overrides": { + "php": "7.3" + }, "plugin-api-version": "2.1.0" } From c3237172e0004a1ac51a522fd54de9ba6cec2cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Wed, 29 Dec 2021 13:25:47 +0100 Subject: [PATCH 5/6] Fix public link file creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- appinfo/routes.php | 3 +- lib/Controller/DocumentAPIController.php | 139 +++++++++++++++++++++++ lib/Controller/DocumentController.php | 121 +------------------- lib/TemplateManager.php | 18 +++ src/services/api.js | 38 +++++++ src/view/NewFileMenu.js | 33 +++--- tests/psalm-baseline.xml | 14 ++- 7 files changed, 230 insertions(+), 136 deletions(-) create mode 100644 lib/Controller/DocumentAPIController.php create mode 100644 src/services/api.js diff --git a/appinfo/routes.php b/appinfo/routes.php index 877616ddf1..57e4edc8ef 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -34,7 +34,6 @@ ['name' => 'document#createFromTemplate', 'url' => 'indexTemplate', 'verb' => 'GET'], ['name' => 'document#publicPage', 'url' => '/public', 'verb' => 'GET'], - ['name' => 'document#create', 'url' => 'ajax/documents/create', 'verb' => 'POST'], // external api access ['name' => 'document#extAppGetData', 'url' => '/ajax/extapp/data/{fileId}', 'verb' => 'POST'], @@ -67,6 +66,8 @@ ['name' => 'templates#delete', 'url' => '/template/{fileId}', 'verb' => 'DELETE'], ], 'ocs' => [ + ['name' => 'documentAPI#create', 'url' => '/api/v1/file', 'verb' => 'POST'], + ['name' => 'OCS#createDirect', 'url' => '/api/v1/document', 'verb' => 'POST'], ['name' => 'OCS#createPublic', 'url' => '/api/v1/share', 'verb' => 'POST'], ['name' => 'OCS#createPublicFromInitiator', 'url' => '/api/v1/direct/share/initiator', 'verb' => 'POST'], diff --git a/lib/Controller/DocumentAPIController.php b/lib/Controller/DocumentAPIController.php new file mode 100644 index 0000000000..86cb2081e6 --- /dev/null +++ b/lib/Controller/DocumentAPIController.php @@ -0,0 +1,139 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +declare(strict_types=1); + +namespace OCA\Richdocuments\Controller; + +use Exception; +use OCA\Richdocuments\AppInfo\Application; +use OCA\Richdocuments\Helper; +use OCA\Richdocuments\TemplateManager; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\JSONResponse; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\IL10N; +use OCP\IRequest; +use OCP\Share\IManager; +use Psr\Log\LoggerInterface; +use Throwable; + +class DocumentAPIController extends \OCP\AppFramework\OCSController { + + private $rootFolder; + private $shareManager; + private $templateManager; + private $l10n; + private $logger; + private $userId; + + public function __construct(IRequest $request, IRootFolder $rootFolder, IManager $shareManager, TemplateManager $templateManager, IL10N $l10n, LoggerInterface $logger, $userId) { + parent::__construct(Application::APPNAME, $request); + $this->rootFolder = $rootFolder; + $this->shareManager = $shareManager; + $this->templateManager = $templateManager; + $this->l10n = $l10n; + $this->logger = $logger; + $this->userId = $userId; + } + + /** + * @NoAdminRequired + * @PublicPage + */ + public function create(string $mimeType, string $fileName, string $directoryPath = '/', string $shareToken = null): JSONResponse { + try { + if ($shareToken !== null) { + $share = $this->shareManager->getShareByToken($shareToken); + } + + $rootFolder = $shareToken !== null ? $share->getNode() : $this->rootFolder->getUserFolder($this->userId); + $folder = $rootFolder->get($directoryPath); + + if (!($folder instanceof Folder)) { + throw new Exception('Node is not a folder'); + } + } catch (Throwable $e) { + $this->logger->error('Failed to create document', ['exception' => $e]); + return new JSONResponse([ + 'status' => 'error', + 'message' => $this->l10n->t('Cannot create document') + ], Http::STATUS_BAD_REQUEST); + } + + $basename = $this->l10n->t('New Document.odt'); + switch ($mimeType) { + case 'application/vnd.oasis.opendocument.spreadsheet': + $basename = $this->l10n->t('New Spreadsheet.ods'); + break; + case 'application/vnd.oasis.opendocument.presentation': + $basename = $this->l10n->t('New Presentation.odp'); + break; + case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': + $basename = $this->l10n->t('New Document.docx'); + break; + case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': + $basename = $this->l10n->t('New Spreadsheet.xlsx'); + break; + case 'application/vnd.openxmlformats-officedocument.presentationml.presentation': + $basename = $this->l10n->t('New Presentation.pptx'); + break; + default: + break; + } + + if (!$fileName) { + $fileName = Helper::getNewFileName($folder, $basename); + } + + if ($folder->nodeExists($fileName)) { + return new JSONResponse([ + 'status' => 'error', + 'message' => $this->l10n->t('File already exists') + ], Http::STATUS_BAD_REQUEST); + } + + try { + $file = $folder->newFile($fileName); + $templateType = $this->templateManager->getTemplateTypeForExtension(pathinfo($fileName, PATHINFO_EXTENSION)); + $empty = $this->templateManager->getEmpty($templateType); + $templateFile = array_shift($empty); + $file->putContent($this->templateManager->getEmptyFileContent($file->getExtension())); + if ($this->templateManager->isSupportedTemplateSource($templateFile->getExtension())) { + // Only use TemplateSource if supported filetype + $this->templateManager->setTemplateSource($file->getId(), $templateFile->getId()); + } + } catch (Exception $e) { + $this->logger->error('Failed to create file from template', ['exception' => $e]); + return new JSONResponse([ + 'status' => 'error', + 'message' => $this->l10n->t('Not allowed to create document') + ], Http::STATUS_BAD_REQUEST); + } + return new JSONResponse([ + 'status' => 'success', + 'data' => \OCA\Files\Helper::formatFileInfo($file->getFileInfo()) + ]); + } +} diff --git a/lib/Controller/DocumentController.php b/lib/Controller/DocumentController.php index 8e1932a20b..23e1bde5ab 100644 --- a/lib/Controller/DocumentController.php +++ b/lib/Controller/DocumentController.php @@ -11,19 +11,16 @@ namespace OCA\Richdocuments\Controller; -use OCA\Richdocuments\AppInfo\Application; use OCA\Richdocuments\Events\BeforeFederationRedirectEvent; use OCA\Richdocuments\Service\FederationService; use OCA\Richdocuments\Service\InitialStateService; +use OCA\Richdocuments\TemplateManager; use OCA\Richdocuments\TokenManager; use \OCP\AppFramework\Controller; -use OCP\AppFramework\Http; -use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\RedirectResponse; use OCP\Constants; use OCP\Files\File; use OCP\Files\Folder; -use OCP\Files\GenericFileException; use OCP\Files\IRootFolder; use OCP\Files\Node; use OCP\Files\NotFoundException; @@ -36,18 +33,14 @@ use \OCP\AppFramework\Http\FeaturePolicy; use \OCP\AppFramework\Http\TemplateResponse; use \OCA\Richdocuments\AppConfig; -use \OCA\Richdocuments\Helper; use OCP\ISession; use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\IManager; -use OC\Files\Type\TemplateManager; class DocumentController extends Controller { /** @var string */ private $uid; - /** @var IL10N */ - private $l10n; /** @var IConfig */ private $config; /** @var AppConfig */ @@ -62,36 +55,30 @@ class DocumentController extends Controller { private $session; /** @var IRootFolder */ private $rootFolder; - /** @var \OCA\Richdocuments\TemplateManager */ + /** @var TemplateManager */ private $templateManager; /** @var FederationService */ private $federationService; /** @var InitialStateService */ private $initialState; - const ODT_TEMPLATE_PATH = '/emptyTemplates/odttemplate.odt'; - - public function __construct( $appName, IRequest $request, IConfig $config, AppConfig $appConfig, - IL10N $l10n, IManager $shareManager, TokenManager $tokenManager, IRootFolder $rootFolder, ISession $session, $UserId, ILogger $logger, - \OCA\Richdocuments\TemplateManager $templateManager, + TemplateManager $templateManager, FederationService $federationService, - Helper $helper, InitialStateService $initialState ) { parent::__construct($appName, $request); $this->uid = $UserId; - $this->l10n = $l10n; $this->config = $config; $this->appConfig = $appConfig; $this->shareManager = $shareManager; @@ -501,108 +488,6 @@ public function remote($shareToken, $remoteServer, $remoteServerToken, $filePath return new TemplateResponse('core', '403', [], 'guest'); } - /** - * @NoAdminRequired - * - * @param string $mimetype - * @param string $filename - * @param string $dir - * @return JSONResponse - * @throws NotPermittedException - * @throws GenericFileException - */ - public function create($mimetype, - $filename, - $dir = '/'){ - - $root = $this->rootFolder->getUserFolder($this->uid); - try { - /** @var Folder $folder */ - $folder = $root->get($dir); - } catch (NotFoundException $e) { - return new JSONResponse([ - 'status' => 'error', - 'message' => $this->l10n->t('Cannot create document') - ], Http::STATUS_BAD_REQUEST); - } - - if (!($folder instanceof Folder)) { - return new JSONResponse([ - 'status' => 'error', - 'message' => $this->l10n->t('Cannot create document') - ], Http::STATUS_BAD_REQUEST); - } - - $basename = $this->l10n->t('New Document.odt'); - switch ($mimetype) { - case 'application/vnd.oasis.opendocument.spreadsheet': - $basename = $this->l10n->t('New Spreadsheet.ods'); - break; - case 'application/vnd.oasis.opendocument.presentation': - $basename = $this->l10n->t('New Presentation.odp'); - break; - case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': - $basename = $this->l10n->t('New Document.docx'); - break; - case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': - $basename = $this->l10n->t('New Spreadsheet.xlsx'); - break; - case 'application/vnd.openxmlformats-officedocument.presentationml.presentation': - $basename = $this->l10n->t('New Presentation.pptx'); - break; - default: - // to be safe - $mimetype = 'application/vnd.oasis.opendocument.text'; - break; - } - - if (!$filename){ - $filename = Helper::getNewFileName($folder, $basename); - } - - if ($folder->nodeExists($filename)) { - return new JSONResponse([ - 'status' => 'error', - 'message' => $this->l10n->t('Document already exists') - ], Http::STATUS_BAD_REQUEST); - } - - try { - $file = $folder->newFile($filename); - } catch (NotPermittedException $e) { - return new JSONResponse([ - 'status' => 'error', - 'message' => $this->l10n->t('Not allowed to create document') - ], Http::STATUS_BAD_REQUEST); - } - - $content = ''; - if (class_exists(TemplateManager::class)){ - $manager = \OC_Helper::getFileTemplateManager(); - $content = $manager->getTemplate($mimetype); - } - - if (!$content){ - // FIXME: see if this is used, - $content = file_get_contents(dirname(dirname(__DIR__)) . self::ODT_TEMPLATE_PATH); - } - - if ($content) { - $file->putContent($content); - - return new JSONResponse([ - 'status' => 'success', - 'data' => \OCA\Files\Helper::formatFileInfo($file->getFileInfo()) - ]); - } - - - return new JSONResponse([ - 'status' => 'error', - 'message' => $this->l10n->t('Cannot create document') - ]); - } - private function renderErrorPage($message) { $params = [ 'errors' => [['error' => $message]] diff --git a/lib/TemplateManager.php b/lib/TemplateManager.php index 1f4d14991e..803f8be90c 100644 --- a/lib/TemplateManager.php +++ b/lib/TemplateManager.php @@ -197,6 +197,24 @@ private function filterTemplates($templates, $type = null) { }); } + public function getTemplateTypeForExtension(string $extension): ?string { + switch ($extension) { + case 'odt': + case 'docx': + return 'document'; + case 'ods': + case 'xlsx': + return 'spreadsheet'; + case 'odp': + case 'pptx': + return 'presentation'; + case 'odg': + return 'drawing'; + } + + return null; + } + public function getEmpty($type = null) { $folder = $this->getEmptyTemplateDir(); diff --git a/src/services/api.js b/src/services/api.js new file mode 100644 index 0000000000..cd5d98add0 --- /dev/null +++ b/src/services/api.js @@ -0,0 +1,38 @@ +/* + * @copyright Copyright (c) 2021 Julius Härtl + * + * @author Julius Härtl + * + * @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 . + * + */ + +import axios from '@nextcloud/axios' +import { generateOcsUrl } from '@nextcloud/router' + +export const createEmptyFile = async(mimeType, fileName) => { + const shareToken = document.getElementById('sharingToken')?.value + const directoryPath = document.getElementById('dir')?.value + + const response = await axios.post(generateOcsUrl('apps/richdocuments/api/v1', 2) + 'file', { + mimeType, + fileName, + directoryPath, + shareToken, + }) + + return response.data +} diff --git a/src/view/NewFileMenu.js b/src/view/NewFileMenu.js index d713864a16..5402d1ff96 100644 --- a/src/view/NewFileMenu.js +++ b/src/view/NewFileMenu.js @@ -21,6 +21,9 @@ */ import Types from '../helpers/types' +import { createEmptyFile } from '../services/api' + +const isPublic = window.document.getElementById('isPublic')?.value === '1' /** @type OC.Plugin */ const NewFileMenu = { @@ -37,7 +40,7 @@ const NewFileMenu = { iconClass: 'icon-filetype-document', fileType: 'x-office-document', actionHandler(filename) { - if (OC.getCapabilities().richdocuments.templates) { + if (!isPublic && OC.getCapabilities().richdocuments.templates) { self._openTemplatePicker('document', document.mime, filename) } else { self._createDocument(document.mime, filename) @@ -52,7 +55,7 @@ const NewFileMenu = { iconClass: 'icon-filetype-spreadsheet', fileType: 'x-office-spreadsheet', actionHandler(filename) { - if (OC.getCapabilities().richdocuments.templates) { + if (!isPublic && OC.getCapabilities().richdocuments.templates) { self._openTemplatePicker('spreadsheet', spreadsheet.mime, filename) } else { self._createDocument(spreadsheet.mime, filename) @@ -67,7 +70,7 @@ const NewFileMenu = { iconClass: 'icon-filetype-presentation', fileType: 'x-office-presentation', actionHandler(filename) { - if (OC.getCapabilities().richdocuments.templates) { + if (!isPublic && OC.getCapabilities().richdocuments.templates) { self._openTemplatePicker('presentation', presentation.mime, filename) } else { self._createDocument(presentation.mime, filename) @@ -80,17 +83,21 @@ const NewFileMenu = { OCA.Files.Files.isFileNameValid(filename) filename = FileList.getUniqueName(filename) - $.post( - OC.generateUrl('apps/richdocuments/ajax/documents/create'), - { mimetype, filename, dir: document.getElementById('dir').value }, - function(response) { - if (response && response.status === 'success') { - FileList.add(response.data, { animate: true, scrollTo: true }) - } else { - OC.dialogs.alert(response.data.message, t('core', 'Could not create file')) - } + createEmptyFile(mimetype, filename).then((response) => { + if (response && response.status === 'success') { + FileList.add(response.data, { animate: true, scrollTo: true }) + const fileModel = FileList.getModelForFile(filename) + const fileAction = OCA.Files.fileActions.getDefaultFileAction(fileModel.get('mimetype'), 'file', OC.PERMISSION_ALL) + fileAction.action(filename, { + $file: null, + dir: FileList.getCurrentDirectory(), + FileList, + fileActions: FileList.fileActions, + }) + } else { + OC.dialogs.alert(response.data.message, t('core', 'Could not create file')) } - ) + }) }, _createDocumentFromTemplate(templateId, mimetype, filename) { diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml index d705ac7aa6..9e44e9d3f3 100644 --- a/tests/psalm-baseline.xml +++ b/tests/psalm-baseline.xml @@ -59,6 +59,14 @@ IRootFolder + + + IRootFolder + + + \OCA\Files\Helper + + $fileId @@ -67,8 +75,7 @@ $item->getId() $node->getId() - - $this->rootFolder + $this->rootFolder $this->rootFolder $this->rootFolder @@ -80,9 +87,8 @@ $app !== '' - + \OCA\Files_Sharing\External\Storage - \OC_Helper getRemote From 6b96051be54ce93ee7b8b4256a42ee7caf3bddd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Fri, 14 Jan 2022 13:27:06 +0100 Subject: [PATCH 6/6] Add controller description and fix typings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- lib/Controller/DocumentAPIController.php | 6 ++++++ lib/TemplateManager.php | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/Controller/DocumentAPIController.php b/lib/Controller/DocumentAPIController.php index 86cb2081e6..dc15544671 100644 --- a/lib/Controller/DocumentAPIController.php +++ b/lib/Controller/DocumentAPIController.php @@ -59,6 +59,12 @@ public function __construct(IRequest $request, IRootFolder $rootFolder, IManager } /** + * Create a file from a public share link of a folder + * + * As the server template API for file creation is not available there, we need a dedicated API + * in order to properly create files as public page visitors. This is being called in the new file + * actions in src/view/NewFileMenu.js + * * @NoAdminRequired * @PublicPage */ diff --git a/lib/TemplateManager.php b/lib/TemplateManager.php index 803f8be90c..f32b31ed00 100644 --- a/lib/TemplateManager.php +++ b/lib/TemplateManager.php @@ -107,7 +107,7 @@ class TemplateManager { ]; public function __construct( - $userId, + ?string $userId, IConfig $config, IAppData $appData, IURLGenerator $urlGenerator, @@ -144,7 +144,7 @@ private function ensureAppDataFolders() { } } - public function setUserId($userId) { + public function setUserId(?string $userId): void { $this->userId = $userId; }