From 8345bbc5aa33a0ab46e3cbf8dd3d4e541a1ba362 Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Wed, 21 Oct 2026 19:06:24 +0200 Subject: [PATCH] Allow disallowing code/table BBCodes and always forbid headings in signatures ref https://www.woltlab.com/community/thread/278819-nicht-erlaubte-bbcodes-bei-der-signatur-erweitern/ --- com.woltlab.wcf/templates/shared_wysiwyg.tpl | 6 +++--- .../bbcode/MessagePreviewAction.class.php | 9 ++++---- .../lib/data/user/UserProfileAction.class.php | 9 ++++---- .../files/lib/form/MessageForm.class.php | 16 +++++++------- .../lib/system/bbcode/BBCodeHandler.class.php | 16 ++++++++++++++ .../users/RenderSignaturePreview.class.php | 9 ++++---- .../field/wysiwyg/WysiwygFormField.class.php | 21 +++++++++---------- .../node/HtmlInputNodeProcessor.class.php | 12 +++++++---- .../BBCodeSelectUserGroupOptionType.class.php | 2 -- 9 files changed, 57 insertions(+), 43 deletions(-) diff --git a/com.woltlab.wcf/templates/shared_wysiwyg.tpl b/com.woltlab.wcf/templates/shared_wysiwyg.tpl index d5be9d72d59..8447439b6e6 100644 --- a/com.woltlab.wcf/templates/shared_wysiwyg.tpl +++ b/com.woltlab.wcf/templates/shared_wysiwyg.tpl @@ -70,11 +70,11 @@ attachment: enableAttachments, autosave: element.dataset.autosave || "", code: true, - codeBlock: true, + codeBlock: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('code')}true{else}false{/if}, fontColor: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('color')}true{else}false{/if}, fontFamily: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('font')}true{else}false{/if}, fontSize: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('size')}true{else}false{/if}, - heading: true, + heading: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('heading')}true{else}false{/if}, html: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('html')}true{else}false{/if}, image: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('img')}true{else}false{/if}, link: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('url')}true{else}false{/if}, @@ -88,7 +88,7 @@ subscript: true, superscript: true, spoiler: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('spoiler')}true{else}false{/if}, - table: true, + table: {if $__wcf->getBBCodeHandler()->isAvailableBBCode('table')}true{else}false{/if}, underline: true, undo: true, }; diff --git a/wcfsetup/install/files/lib/data/bbcode/MessagePreviewAction.class.php b/wcfsetup/install/files/lib/data/bbcode/MessagePreviewAction.class.php index ffaa6fa04d1..187740c7f68 100644 --- a/wcfsetup/install/files/lib/data/bbcode/MessagePreviewAction.class.php +++ b/wcfsetup/install/files/lib/data/bbcode/MessagePreviewAction.class.php @@ -9,7 +9,6 @@ use wcf\system\html\output\HtmlOutputProcessor; use wcf\system\message\embedded\object\MessageEmbeddedObjectManager; use wcf\system\WCF; -use wcf\util\ArrayUtil; /** * Provides a default message preview action. @@ -56,10 +55,10 @@ public function getMessagePreview() // set disallowed bbcodes first to ensure proper parsing $disallowedBBCodesPermission = $this->parameters['disallowedBBCodesPermission'] ?? 'user.message.disallowedBBCodes'; if ($disallowedBBCodesPermission !== '') { - BBCodeHandler::getInstance()->setDisallowedBBCodes(ArrayUtil::trim(\explode( - ',', - WCF::getSession()->getPermission($disallowedBBCodesPermission) - ))); + BBCodeHandler::getInstance()->setDisallowedBBCodesFor( + $disallowedBBCodesPermission, + $this->parameters['messageObjectType'] + ); } $htmlInputProcessor = new HtmlInputProcessor(); diff --git a/wcfsetup/install/files/lib/data/user/UserProfileAction.class.php b/wcfsetup/install/files/lib/data/user/UserProfileAction.class.php index 99513e043cf..95d528fcdab 100644 --- a/wcfsetup/install/files/lib/data/user/UserProfileAction.class.php +++ b/wcfsetup/install/files/lib/data/user/UserProfileAction.class.php @@ -16,7 +16,6 @@ use wcf\system\message\embedded\object\MessageEmbeddedObjectManager; use wcf\system\upload\UploadFile; use wcf\system\WCF; -use wcf\util\ArrayUtil; /** * Executes user profile-related actions. @@ -77,10 +76,10 @@ public function getMessagePreview() WCF::getUser()->userID ); - BBCodeHandler::getInstance()->setDisallowedBBCodes(ArrayUtil::trim(\explode( - ',', - WCF::getSession()->getPermission('user.signature.disallowedBBCodes') - ))); + BBCodeHandler::getInstance()->setDisallowedBBCodesFor( + 'user.signature.disallowedBBCodes', + 'com.woltlab.wcf.user.signature' + ); $disallowedBBCodes = $htmlInputProcessor->validate(); if ($disallowedBBCodes !== []) { throw new UserInputException( diff --git a/wcfsetup/install/files/lib/form/MessageForm.class.php b/wcfsetup/install/files/lib/form/MessageForm.class.php index 96739be1c39..6f463a04118 100644 --- a/wcfsetup/install/files/lib/form/MessageForm.class.php +++ b/wcfsetup/install/files/lib/form/MessageForm.class.php @@ -226,10 +226,10 @@ protected function validateText() } if ($this->disallowedBBCodesPermission !== '') { - BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode( - ',', - WCF::getSession()->getPermission($this->disallowedBBCodesPermission) - )); + BBCodeHandler::getInstance()->setDisallowedBBCodesFor( + $this->disallowedBBCodesPermission, + $this->messageObjectType + ); } $this->htmlInputProcessor = new HtmlInputProcessor(); @@ -315,10 +315,10 @@ public function readData() } if ($this->disallowedBBCodesPermission !== '') { - BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode( - ',', - WCF::getSession()->getPermission($this->disallowedBBCodesPermission) - )); + BBCodeHandler::getInstance()->setDisallowedBBCodesFor( + $this->disallowedBBCodesPermission, + $this->messageObjectType + ); } } diff --git a/wcfsetup/install/files/lib/system/bbcode/BBCodeHandler.class.php b/wcfsetup/install/files/lib/system/bbcode/BBCodeHandler.class.php index f1a2be1ec6c..0184bac97df 100644 --- a/wcfsetup/install/files/lib/system/bbcode/BBCodeHandler.class.php +++ b/wcfsetup/install/files/lib/system/bbcode/BBCodeHandler.class.php @@ -139,6 +139,22 @@ public function setDisallowedBBCodes(array $bbCodes) $this->disallowedBBCodes = $bbCodes; } + /** + * Sets the disallowed BBCodes based on the given user group permission. Headings are + * always disallowed in signatures. + * + * @since 6.3 + */ + public function setDisallowedBBCodesFor(string $permission, string $messageObjectType): void + { + $bbCodes = \explode(',', (string)WCF::getSession()->getPermission($permission)); + if ($messageObjectType === 'com.woltlab.wcf.user.signature') { + $bbCodes[] = 'heading'; + } + + $this->setDisallowedBBCodes($bbCodes); + } + /** * Returns a list of BBCodes which contain raw code (disabled BBCode parsing) * diff --git a/wcfsetup/install/files/lib/system/endpoint/controller/core/users/RenderSignaturePreview.class.php b/wcfsetup/install/files/lib/system/endpoint/controller/core/users/RenderSignaturePreview.class.php index f9145d48822..daf0a14f844 100644 --- a/wcfsetup/install/files/lib/system/endpoint/controller/core/users/RenderSignaturePreview.class.php +++ b/wcfsetup/install/files/lib/system/endpoint/controller/core/users/RenderSignaturePreview.class.php @@ -15,7 +15,6 @@ use wcf\system\html\output\HtmlOutputProcessor; use wcf\system\message\embedded\object\MessageEmbeddedObjectManager; use wcf\system\WCF; -use wcf\util\ArrayUtil; /** * Renders the preview of the active user's signature. @@ -41,10 +40,10 @@ public function __invoke(ServerRequestInterface $request, array $variables): Res $parameters = Helper::mapApiParameters($request, RenderSignaturePreviewParameters::class); - BBCodeHandler::getInstance()->setDisallowedBBCodes(ArrayUtil::trim(\explode( - ',', - WCF::getSession()->getPermission('user.signature.disallowedBBCodes') - ))); + BBCodeHandler::getInstance()->setDisallowedBBCodesFor( + 'user.signature.disallowedBBCodes', + 'com.woltlab.wcf.user.signature' + ); $htmlInputProcessor = new HtmlInputProcessor(); $htmlInputProcessor->process( diff --git a/wcfsetup/install/files/lib/system/form/builder/field/wysiwyg/WysiwygFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/wysiwyg/WysiwygFormField.class.php index 15af6eb78ae..c95d3d9924e 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/wysiwyg/WysiwygFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/wysiwyg/WysiwygFormField.class.php @@ -26,7 +26,6 @@ use wcf\system\l10n\L10nStorage; use wcf\system\language\LanguageFactory; use wcf\system\message\quote\MessageQuoteManager; -use wcf\system\WCF; use wcf\util\StringUtil; /** @@ -154,10 +153,10 @@ public function getFieldHtml(): string $disallowedBBCodesPermission = 'user.message.disallowedBBCodes'; } - BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode( - ',', - WCF::getSession()->getPermission($disallowedBBCodesPermission) - )); + BBCodeHandler::getInstance()->setDisallowedBBCodesFor( + $disallowedBBCodesPermission, + $this->getObjectType()->objectType + ); return parent::getFieldHtml(); } @@ -245,7 +244,7 @@ public function getL10nValues(): array } return \array_map( - static fn (HtmlInputProcessor $htmlInputProcessor) => $htmlInputProcessor->getHtml(), + static fn(HtmlInputProcessor $htmlInputProcessor) => $htmlInputProcessor->getHtml(), $this->htmlInputProcessors ); } @@ -420,10 +419,10 @@ public function validate(): void $disallowedBBCodesPermission = 'user.message.disallowedBBCodes'; } - BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode( - ',', - WCF::getSession()->getPermission($disallowedBBCodesPermission) - )); + BBCodeHandler::getInstance()->setDisallowedBBCodesFor( + $disallowedBBCodesPermission, + $this->getObjectType()->objectType + ); if ($this->isL10n()) { $this->validateL10n(); @@ -538,7 +537,7 @@ public function value(mixed $value): static $value = $this->upcast($value); } elseif (\is_array($value)) { $value = \array_map( - fn ($languageValue) => \is_string($languageValue) ? $this->upcast($languageValue) : $languageValue, + fn($languageValue) => \is_string($languageValue) ? $this->upcast($languageValue) : $languageValue, $value ); } diff --git a/wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeProcessor.class.php b/wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeProcessor.class.php index 880a0d236e3..c938a920769 100644 --- a/wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeProcessor.class.php +++ b/wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeProcessor.class.php @@ -602,16 +602,20 @@ function (IHtmlNode $nodeHandler) use (&$result) { // handle custom nodes that have no dedicated handler $customTags = [ - 'spoiler' => 'woltlab-spoiler', - 'url' => 'a', + // `
` represents the HTML bbcode
+            'code' => "//pre[not(contains(concat(' ', normalize-space(@class), ' '), ' woltlabHtml '))]",
+            'heading' => '//h1 | //h2 | //h3 | //h4 | //h5 | //h6',
+            'spoiler' => '//woltlab-spoiler',
+            'table' => '//table',
+            'url' => '//a',
         ];
 
-        foreach ($customTags as $bbcode => $tagName) {
+        foreach ($customTags as $bbcode => $query) {
             if (BBCodeHandler::getInstance()->isAvailableBBCode($bbcode)) {
                 continue;
             }
 
-            if ($this->getDocument()->getElementsByTagName($tagName)->length !== 0) {
+            if ($this->getXPath()->query($query)->length !== 0) {
                 $result[] = $bbcode;
             }
         }
diff --git a/wcfsetup/install/files/lib/system/option/user/group/BBCodeSelectUserGroupOptionType.class.php b/wcfsetup/install/files/lib/system/option/user/group/BBCodeSelectUserGroupOptionType.class.php
index 9b3d09d2c17..8172b5f87e6 100644
--- a/wcfsetup/install/files/lib/system/option/user/group/BBCodeSelectUserGroupOptionType.class.php
+++ b/wcfsetup/install/files/lib/system/option/user/group/BBCodeSelectUserGroupOptionType.class.php
@@ -32,14 +32,12 @@ class BBCodeSelectUserGroupOptionType extends AbstractOptionType implements IUse
         'align',
         'attach',
         'b',
-        'code',
         'i',
         'list',
         'quote',
         's',
         'sub',
         'sup',
-        'table',
         'td',
         'tr',
         'tt',