From e146bf163efb5b33fac53cb9f66d0c7a23bc4eb1 Mon Sep 17 00:00:00 2001 From: Joly0 <13993216+Joly0@users.noreply.github.com> Date: Sat, 3 Jan 2026 13:23:13 +0100 Subject: [PATCH] Allow PDF Forms calculations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR configures the pdf viewer to allow calculations (secure in a sandbox). Can be enabled/disabled through the admin settings globally, default is disabled. Uses pdf.js´s sandbox feature, which should make this as secure as it can get. Fixes https://github.com/nextcloud/files_pdfviewer/issues/1265 --- appinfo/routes.php | 2 + lib/AppInfo/Application.php | 3 + lib/Controller/SettingsController.php | 63 +++++++++++++++++++++ lib/Settings/AdminSettings.php | 36 ++++++++++++ src/admin.js | 12 ++++ src/components/AdminSettings.vue | 79 +++++++++++++++++++++++++++ src/views/PDFView.vue | 2 +- templates/admin.php | 10 ++++ webpack.config.js | 1 + 9 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 lib/Controller/SettingsController.php create mode 100644 lib/Settings/AdminSettings.php create mode 100644 src/admin.js create mode 100644 src/components/AdminSettings.vue create mode 100644 templates/admin.php diff --git a/appinfo/routes.php b/appinfo/routes.php index f45661fd..755ebd77 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -10,4 +10,6 @@ return ['routes' => [ ['name' => 'display#showPdfViewer', 'url' => '/', 'verb' => 'GET'], + ['name' => 'settings#getSettings', 'url' => '/settings', 'verb' => 'GET'], + ['name' => 'settings#setSettings', 'url' => '/settings', 'verb' => 'POST'], ]]; diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index ea6259b8..8c4e871a 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -9,6 +9,7 @@ use OCA\Files_PDFViewer\Listeners\CSPListener; use OCA\Files_PDFViewer\Listeners\LoadViewerListener; +use OCA\Files_PDFViewer\Settings\AdminSettings; use OCA\Viewer\Event\LoadViewer; @@ -31,5 +32,7 @@ public function register(IRegistrationContext $context): void { } public function boot(IBootContext $context): void { + $server = $context->getServerContainer(); + $server->getSettingsManager()->registerSetting('admin', AdminSettings::class); } } diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php new file mode 100644 index 00000000..8078f448 --- /dev/null +++ b/lib/Controller/SettingsController.php @@ -0,0 +1,63 @@ +config = $config; + } + + /** + * Get current PDF scripting setting + */ + #[AuthorizedAdminSetting(settings: \OCA\Files_PDFViewer\Settings\AdminSettings::class)] + public function getSettings(): JSONResponse { + $enableScripting = $this->config->getAppValue( + Application::APP_ID, + 'enable_scripting', + 'no' + ) === 'yes'; + + return new JSONResponse([ + 'enableScripting' => $enableScripting, + ]); + } + + + /** + * Update PDF scripting setting + */ + #[AuthorizedAdminSetting(settings: \OCA\Files_PDFViewer\Settings\AdminSettings::class)] + public function setSettings(bool $enableScripting): JSONResponse { + $this->config->setAppValue( + Application::APP_ID, + 'enable_scripting', + $enableScripting ? 'yes' : 'no' + ); + + return new JSONResponse([ + 'enableScripting' => $enableScripting, + ]); + } +} diff --git a/lib/Settings/AdminSettings.php b/lib/Settings/AdminSettings.php new file mode 100644 index 00000000..b504a526 --- /dev/null +++ b/lib/Settings/AdminSettings.php @@ -0,0 +1,36 @@ +config = $config; + } + + public function getForm(): TemplateResponse { + return new TemplateResponse(Application::APP_ID, 'admin', []); + } + + public function getSection(): string { + return 'server'; + } + + public function getPriority(): int { + return 50; + } +} diff --git a/src/admin.js b/src/admin.js new file mode 100644 index 00000000..4a3d9c1f --- /dev/null +++ b/src/admin.js @@ -0,0 +1,12 @@ +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +import Vue from 'vue' +import AdminSettings from './components/AdminSettings.vue' + +Vue.prototype.t = t +Vue.prototype.n = n + +const View = Vue.extend(AdminSettings) +new View().$mount('#files_pdfviewer-admin-settings') diff --git a/src/components/AdminSettings.vue b/src/components/AdminSettings.vue new file mode 100644 index 00000000..c439fd97 --- /dev/null +++ b/src/components/AdminSettings.vue @@ -0,0 +1,79 @@ + + + + diff --git a/src/views/PDFView.vue b/src/views/PDFView.vue index 26350a5d..c9e4706a 100644 --- a/src/views/PDFView.vue +++ b/src/views/PDFView.vue @@ -145,7 +145,7 @@ export default { PDFViewerApplicationOptions.set('sandboxBundleSrc', this.getViewerTemplateParameter('sandbox')) PDFViewerApplicationOptions.set('enablePermissions', true) PDFViewerApplicationOptions.set('imageResourcesPath', this.getViewerTemplateParameter('imageresourcespath')) - PDFViewerApplicationOptions.set('enableScripting', this.getViewerTemplateParameter('enableScripting') === true) + PDFViewerApplicationOptions.set('enableScripting', this.getViewerTemplateParameter('enableScripting') === '1') const language = getLanguage() const supportedLanguages = SUPPORTED_LANGUAGES diff --git a/templates/admin.php b/templates/admin.php new file mode 100644 index 00000000..f8e8a619 --- /dev/null +++ b/templates/admin.php @@ -0,0 +1,10 @@ + + +
diff --git a/webpack.config.js b/webpack.config.js index b1457de5..d7bf91b3 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -13,6 +13,7 @@ const { readdirSync } = require('fs') const l10nContent = readdirSync(path.resolve(__dirname, 'js', 'pdfjs', 'web', 'locale')) webpackConfig.entry.workersrc = path.resolve(path.join('src', 'workersrc.js')) +webpackConfig.entry.admin = path.resolve(path.join('src', 'admin.js')) // keep pdfjs vendor in the js folder webpackConfig.output.clean = false