Added missing class name filter
authorAlexander Ebert <ebert@woltlab.com>
Thu, 22 Sep 2016 14:34:55 +0000 (16:34 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Thu, 22 Sep 2016 14:35:01 +0000 (16:35 +0200)
wcfsetup/install/files/lib/system/html/input/filter/MessageHtmlInputFilter.class.php
wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeProcessor.class.php

index 0253362cfb4b7c381903ec93961103db6c4028fe..22ce9eaab18c1f9f22303952244fef47447a61d7 100644 (file)
@@ -33,6 +33,9 @@ class MessageHtmlInputFilter implements IHtmlInputFilter {
        protected function getPurifier() {
                if (self::$purifier === null) {
                        $config = \HTMLPurifier_Config::createDefault();
+                       $config->set('HTML.ForbiddenAttributes', ['*@style', '*@lang', '*@xml:lang']);
+                       $config->set('HTML.ForbiddenElements', ['span']);
+                       
                        $this->setAttributeDefinitions($config);
                        self::$purifier = new \HTMLPurifier($config);
                }
index 9efc34809812dac1ba1d77ed1af4293dbb7a09d8..d841eeb6dccf4b2eb5077edf60f93924a4e87088 100644 (file)
@@ -17,6 +17,40 @@ use wcf\util\StringUtil;
  * @since       3.0
  */
 class HtmlInputNodeProcessor extends AbstractHtmlNodeProcessor {
+       /**
+        * list of allowed CSS class names per tag name
+        * @var array<array>
+        */
+       public static $allowedClassNames = [
+               'img' => [
+                       // float left/right
+                       'messageFloatObjectLeft', 'messageFloatObjectRight',
+                       
+                       // built-in
+                       'smiley', 'woltlabAttachment', 'woltlabSuiteMedia'
+               ],
+               'p' => [
+                       // text alignment
+                       'text-center', 'text-justify', 'text-right',
+                       
+                       // text color
+                       '.woltlab-color-000000', '.woltlab-color-000080', '.woltlab-color-0000CD', '.woltlab-color-0000FF', '.woltlab-color-006400', '.woltlab-color-008000',
+                       '.woltlab-color-008080', '.woltlab-color-00FF00', '.woltlab-color-00FFFF', '.woltlab-color-2F4F4F', '.woltlab-color-40E0D0', '.woltlab-color-4B0082',
+                       '.woltlab-color-696969', '.woltlab-color-800000', '.woltlab-color-800080', '.woltlab-color-808080', '.woltlab-color-8B4513', '.woltlab-color-A52A2A',
+                       '.woltlab-color-A9A9A9', '.woltlab-color-ADD8E6', '.woltlab-color-AFEEEE', '.woltlab-color-B22222', '.woltlab-color-D3D3D3', '.woltlab-color-DAA520',
+                       '.woltlab-color-DDA0DD', '.woltlab-color-E6E6FA', '.woltlab-color-EE82EE', '.woltlab-color-F0F8FF', '.woltlab-color-F0FFF0', '.woltlab-color-F0FFFF',
+                       '.woltlab-color-FAEBD7', '.woltlab-color-FF0000', '.woltlab-color-FF8C00', '.woltlab-color-FFA07A', '.woltlab-color-FFA500', '.woltlab-color-FFD700',
+                       '.woltlab-color-FFF0F5', '.woltlab-color-FFFF00', '.woltlab-color-FFFFE0', '.woltlab-color-FFFFFF',
+                       
+                       // font size
+                       '.woltlab-size-8', '.woltlab-size-10', '.woltlab-size-12', '.woltlab-size-14', '.woltlab-size-18', '.woltlab-size-24', '.woltlab-size-36',
+                       
+                       // font family
+                       '.woltlab-font-arial', '.woltlab-font-comicSansMs', '.woltlab-font-courierNew', '.woltlab-font-georgia', '.woltlab-font-lucidaSansUnicode',
+                       '.woltlab-font-tahoma', '.woltlab-font-timesNewRoman', '.woltlab-font-trebuchetMs', '.woltlab-font-verdana'
+               ]
+       ];
+       
        /**
         * list of embedded content grouped by type
         * @var array
@@ -59,6 +93,26 @@ class HtmlInputNodeProcessor extends AbstractHtmlNodeProcessor {
                $textParser = new HtmlInputNodeTextParser($this);
                $textParser->parse();
                
+               // strip invalid class names
+               /** @var \DOMElement $element */
+               $before = htmlentities($this->getHtml());
+               foreach ($this->getXPath()->query('//*[@class]') as $element) {
+                       $nodeName = $element->nodeName;
+                       if (isset(self::$allowedClassNames[$nodeName])) {
+                               $classNames = explode(' ', $element->getAttribute('class'));
+                               $classNames = array_filter($classNames, function ($className) use ($nodeName) {
+                                       return  ($className && in_array($className, self::$allowedClassNames[$nodeName]));
+                               });
+                               
+                               if (!empty($classNames)) {
+                                       $element->setAttribute('class', implode(' ', $classNames));
+                                       continue;
+                               }
+                       }
+                       
+                       $element->removeAttribute('class');
+               }
+               
                // extract embedded content
                $this->processEmbeddedContent();