]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-19871 imported htmlpurifier 4.0.0
authorskodak <skodak>
Sun, 19 Jul 2009 11:56:56 +0000 (11:56 +0000)
committerskodak <skodak>
Sun, 19 Jul 2009 11:56:56 +0000 (11:56 +0000)
84 files changed:
lib/htmlpurifier/HTMLPurifier.php
lib/htmlpurifier/HTMLPurifier.safe-includes.php
lib/htmlpurifier/HTMLPurifier/AttrDef/CSS/Color.php
lib/htmlpurifier/HTMLPurifier/AttrDef/HTML/Class.php [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/AttrDef/HTML/Color.php
lib/htmlpurifier/HTMLPurifier/AttrDef/HTML/FrameTarget.php
lib/htmlpurifier/HTMLPurifier/AttrDef/HTML/ID.php
lib/htmlpurifier/HTMLPurifier/AttrDef/HTML/LinkTypes.php
lib/htmlpurifier/HTMLPurifier/AttrDef/HTML/Nmtokens.php
lib/htmlpurifier/HTMLPurifier/AttrDef/Lang.php
lib/htmlpurifier/HTMLPurifier/AttrDef/URI.php
lib/htmlpurifier/HTMLPurifier/AttrTransform/BdoDir.php
lib/htmlpurifier/HTMLPurifier/AttrTransform/ImgRequired.php
lib/htmlpurifier/HTMLPurifier/AttrTransform/Name.php
lib/htmlpurifier/HTMLPurifier/AttrTransform/NameSync.php [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/AttrTypes.php
lib/htmlpurifier/HTMLPurifier/CSSDefinition.php
lib/htmlpurifier/HTMLPurifier/ChildDef/Required.php
lib/htmlpurifier/HTMLPurifier/Config.php
lib/htmlpurifier/HTMLPurifier/ConfigSchema.php
lib/htmlpurifier/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php
lib/htmlpurifier/HTMLPurifier/ConfigSchema/Builder/Xml.php
lib/htmlpurifier/HTMLPurifier/ConfigSchema/Interchange.php
lib/htmlpurifier/HTMLPurifier/ConfigSchema/Interchange/Id.php
lib/htmlpurifier/HTMLPurifier/ConfigSchema/Interchange/Namespace.php [deleted file]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/InterchangeBuilder.php
lib/htmlpurifier/HTMLPurifier/ConfigSchema/Validator.php
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema.ser
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Attr.txt [deleted file]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt [moved from lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormatParam.PurifierLinkifyDocURL.txt with 75% similarity]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.txt [deleted file]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormatParam.txt [deleted file]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/CSS.txt [deleted file]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Cache.txt [deleted file]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Core.txt [deleted file]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt [moved from lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/FilterParam.ExtractStyleBlocksEscaping.txt with 75% similarity]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt [moved from lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/FilterParam.ExtractStyleBlocksScope.txt with 90% similarity]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt [moved from lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/FilterParam.ExtractStyleBlocksTidyImpl.txt with 85% similarity]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Filter.txt [deleted file]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/FilterParam.txt [deleted file]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.txt [deleted file]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Output.txt [deleted file]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Test.txt [deleted file]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/URI.txt [deleted file]
lib/htmlpurifier/HTMLPurifier/DefinitionCache.php
lib/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer.php
lib/htmlpurifier/HTMLPurifier/DefinitionCacheFactory.php
lib/htmlpurifier/HTMLPurifier/DoctypeRegistry.php
lib/htmlpurifier/HTMLPurifier/ElementDef.php
lib/htmlpurifier/HTMLPurifier/Encoder.php
lib/htmlpurifier/HTMLPurifier/Filter/ExtractStyleBlocks.php
lib/htmlpurifier/HTMLPurifier/Generator.php
lib/htmlpurifier/HTMLPurifier/HTMLDefinition.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/CommonAttributes.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/Image.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/Name.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/SafeEmbed.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/SafeObject.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/Tidy.php
lib/htmlpurifier/HTMLPurifier/HTMLModuleManager.php
lib/htmlpurifier/HTMLPurifier/IDAccumulator.php
lib/htmlpurifier/HTMLPurifier/Injector.php
lib/htmlpurifier/HTMLPurifier/Injector/PurifierLinkify.php
lib/htmlpurifier/HTMLPurifier/Injector/RemoveEmpty.php
lib/htmlpurifier/HTMLPurifier/LanguageFactory.php
lib/htmlpurifier/HTMLPurifier/Lexer.php
lib/htmlpurifier/HTMLPurifier/Lexer/DOMLex.php
lib/htmlpurifier/HTMLPurifier/Lexer/DirectLex.php
lib/htmlpurifier/HTMLPurifier/Printer/ConfigForm.php
lib/htmlpurifier/HTMLPurifier/Strategy/MakeWellFormed.php
lib/htmlpurifier/HTMLPurifier/Strategy/RemoveForeignElements.php
lib/htmlpurifier/HTMLPurifier/URIDefinition.php
lib/htmlpurifier/HTMLPurifier/URIFilter/HostBlacklist.php
lib/htmlpurifier/HTMLPurifier/URIFilter/Munge.php
lib/htmlpurifier/HTMLPurifier/URISchemeRegistry.php
lib/htmlpurifier/readme_moodle.txt
lib/thirdpartylibs.xml

index 4b1eddecb59f97cda4af8039eea0f3fdfd0d3aeb..e3fce9c2a3462a883c2d64009703aeaaef51c48b 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 /*
-    HTML Purifier 3.3.0 - Standards Compliant HTML Filtering
+    HTML Purifier 4.0.0 - Standards Compliant HTML Filtering
     Copyright (C) 2006-2008 Edward Z. Yang
 
     This library is free software; you can redistribute it and/or
@@ -55,10 +55,10 @@ class HTMLPurifier
 {
 
     /** Version of HTML Purifier */
-    public $version = '3.3.0';
+    public $version = '4.0.0';
 
     /** Constant with version of HTML Purifier */
-    const VERSION = '3.3.0';
+    const VERSION = '4.0.0';
 
     /** Global configuration object */
     public $config;
@@ -128,7 +128,7 @@ class HTMLPurifier
         $context->register('Generator', $this->generator);
 
         // set up global context variables
-        if ($config->get('Core', 'CollectErrors')) {
+        if ($config->get('Core.CollectErrors')) {
             // may get moved out if other facilities use it
             $language_factory = HTMLPurifier_LanguageFactory::instance();
             $language = $language_factory->create($config, $context);
@@ -152,6 +152,7 @@ class HTMLPurifier
         $filters = array();
         foreach ($filter_flags as $filter => $flag) {
             if (!$flag) continue;
+            if (strpos($filter, '.') !== false) continue;
             $class = "HTMLPurifier_Filter_$filter";
             $filters[] = new $class;
         }
index 7d393036a896a5fef42222f8390eeb8a75dd7a56..cf2c1d617a4d2e402b877de907991d39e9c5f7ef 100644 (file)
@@ -92,6 +92,8 @@ require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Percentage.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/CSS/TextDecoration.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/CSS/URI.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Bool.php';
+require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Nmtokens.php';
+require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Class.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Color.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/HTML/FrameTarget.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/HTML/ID.php';
@@ -99,7 +101,6 @@ require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Pixels.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Length.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/HTML/LinkTypes.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/HTML/MultiLength.php';
-require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Nmtokens.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/URI/Host.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv4.php';
@@ -117,6 +118,7 @@ require_once $__dir . '/HTMLPurifier/AttrTransform/Input.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/Lang.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/Length.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/Name.php';
+require_once $__dir . '/HTMLPurifier/AttrTransform/NameSync.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/SafeEmbed.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/SafeObject.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/SafeParam.php';
index 14c6594b6069f55fabe38a14805b079be8badb88..07f95a6719149ca6919d8143c80ead8f24bd54aa 100644 (file)
@@ -9,7 +9,7 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
     public function validate($color, $config, $context) {
 
         static $colors = null;
-        if ($colors === null) $colors = $config->get('Core', 'ColorKeywords');
+        if ($colors === null) $colors = $config->get('Core.ColorKeywords');
 
         $color = trim($color);
         if ($color === '') return false;
diff --git a/lib/htmlpurifier/HTMLPurifier/AttrDef/HTML/Class.php b/lib/htmlpurifier/HTMLPurifier/AttrDef/HTML/Class.php
new file mode 100644 (file)
index 0000000..370068d
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * Implements special behavior for class attribute (normally NMTOKENS)
+ */
+class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens
+{
+    protected function split($string, $config, $context) {
+        // really, this twiddle should be lazy loaded
+        $name = $config->getDefinition('HTML')->doctype->name;
+        if ($name == "XHTML 1.1" || $name == "XHTML 2.0") {
+            return parent::split($string, $config, $context);
+        } else {
+            return preg_split('/\s+/', $string);
+        }
+    }
+    protected function filter($tokens, $config, $context) {
+        $allowed = $config->get('Attr.AllowedClasses');
+        $forbidden = $config->get('Attr.ForbiddenClasses');
+        $ret = array();
+        foreach ($tokens as $token) {
+            if (
+                ($allowed === null || isset($allowed[$token])) &&
+                !isset($forbidden[$token]) &&
+                // We need this O(n) check because of PHP's array
+                // implementation that casts -0 to 0.
+                !in_array($token, $ret, true)
+            ) {
+                $ret[] = $token;
+            }
+        }
+        return $ret;
+    }
+}
index 5311a3c6139631ba1fd02dea5e306a624419f5e0..d01e20454ea9f8385160b3acf7c95c7e5ca2b267 100644 (file)
@@ -9,7 +9,7 @@ class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
     public function validate($string, $config, $context) {
 
         static $colors = null;
-        if ($colors === null) $colors = $config->get('Core', 'ColorKeywords');
+        if ($colors === null) $colors = $config->get('Core.ColorKeywords');
 
         $string = trim($string);
 
index bd281a89fb57a06627db011a30e1a46cce71704d..ae6ea7c01d55c257c4d93acbc2c5468baaaaa01f 100644 (file)
@@ -12,7 +12,7 @@ class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
     public function __construct() {}
 
     public function validate($string, $config, $context) {
-        if ($this->valid_values === false) $this->valid_values = $config->get('Attr', 'AllowedFrameTargets');
+        if ($this->valid_values === false) $this->valid_values = $config->get('Attr.AllowedFrameTargets');
         return parent::validate($string, $config, $context);
     }
 
index 7c5c169c25483dfc6dc93aa6760bf7e56e00dce4..81d03762dea58956773a19786ebf61b70b7b6b69 100644 (file)
@@ -17,18 +17,18 @@ class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
 
     public function validate($id, $config, $context) {
 
-        if (!$config->get('Attr', 'EnableID')) return false;
+        if (!$config->get('Attr.EnableID')) return false;
 
         $id = trim($id); // trim it first
 
         if ($id === '') return false;
 
-        $prefix = $config->get('Attr', 'IDPrefix');
+        $prefix = $config->get('Attr.IDPrefix');
         if ($prefix !== '') {
-            $prefix .= $config->get('Attr', 'IDPrefixLocal');
+            $prefix .= $config->get('Attr.IDPrefixLocal');
             // prevent re-appending the prefix
             if (strpos($id, $prefix) !== 0) $id = $prefix . $id;
-        } elseif ($config->get('Attr', 'IDPrefixLocal') !== '') {
+        } elseif ($config->get('Attr.IDPrefixLocal') !== '') {
             trigger_error('%Attr.IDPrefixLocal cannot be used unless '.
                 '%Attr.IDPrefix is set', E_USER_WARNING);
         }
@@ -51,7 +51,7 @@ class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
             $result = ($trim === '');
         }
 
-        $regexp = $config->get('Attr', 'IDBlacklistRegexp');
+        $regexp = $config->get('Attr.IDBlacklistRegexp');
         if ($regexp && preg_match($regexp, $id)) {
             return false;
         }
index 8a0da0c89e0ccc02aa501b3d4b0d5e33e7dc3005..76d25ed088ace93cf386867f74491e5b3cf73477 100644 (file)
@@ -27,7 +27,7 @@ class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
 
     public function validate($string, $config, $context) {
 
-        $allowed = $config->get('Attr', $this->name);
+        $allowed = $config->get('Attr.' . $this->name);
         if (empty($allowed)) return false;
 
         $string = $this->parseCDATA($string);
index 55035c4d04f57a9e93028c878c9760e763502e76..aa34120bd289543d1b7adbd4f42f8b2ab51f973e 100644 (file)
@@ -2,10 +2,6 @@
 
 /**
  * Validates contents based on NMTOKENS attribute type.
- * @note The only current use for this is the class attribute in HTML
- * @note Could have some functionality factored out into Nmtoken class
- * @warning We cannot assume this class will be used only for 'class'
- *          attributes. Not sure how to hook in magic behavior, then.
  */
 class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
 {
@@ -17,6 +13,17 @@ class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
         // early abort: '' and '0' (strings that convert to false) are invalid
         if (!$string) return false;
 
+        $tokens = $this->split($string, $config, $context);
+        $tokens = $this->filter($tokens, $config, $context);
+        if (empty($tokens)) return false;
+        return implode(' ', $tokens);
+
+    }
+
+    /**
+     * Splits a space separated list of tokens into its constituent parts.
+     */
+    protected function split($string, $config, $context) {
         // OPTIMIZABLE!
         // do the preg_match, capture all subpatterns for reformulation
 
@@ -24,23 +31,20 @@ class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
         // escaping because I don't know how to do that with regexps
         // and plus it would complicate optimization efforts (you never
         // see that anyway).
-        $matches = array();
         $pattern = '/(?:(?<=\s)|\A)'. // look behind for space or string start
                    '((?:--|-?[A-Za-z_])[A-Za-z_\-0-9]*)'.
                    '(?:(?=\s)|\z)/'; // look ahead for space or string end
         preg_match_all($pattern, $string, $matches);
+        return $matches[1];
+    }
 
-        if (empty($matches[1])) return false;
-
-        // reconstruct string
-        $new_string = '';
-        foreach ($matches[1] as $token) {
-            $new_string .= $token . ' ';
-        }
-        $new_string = rtrim($new_string);
-
-        return $new_string;
-
+    /**
+     * Template method for removing certain tokens based on arbitrary criteria.
+     * @note If we wanted to be really functional, we'd do an array_filter
+     *       with a callback. But... we're not.
+     */
+    protected function filter($tokens, $config, $context) {
+        return $tokens;
     }
 
 }
index 48b168948cd204f2ecc94bece14ac05401a2b4d6..0de496c6abeef757a1548988f92a5207c26f0bf7 100644 (file)
@@ -12,7 +12,7 @@ class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
 // moodle change - we use special lang strings unfortunatelly
         return ereg_replace('[^0-9a-zA-Z_-]', '', $string);
 // moodle change end
-        
+
         $string = trim($string);
         if (!$string) return false;
 
index 93d2f0bbf4818b2cc12979a02a65015c7b1a3f95..01a6d83e9526f81e3983863f04f8505d39ae2b36 100644 (file)
@@ -25,7 +25,7 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
 
     public function validate($uri, $config, $context) {
 
-        if ($config->get('URI', 'Disable')) return false;
+        if ($config->get('URI.Disable')) return false;
 
         $uri = $this->parseCDATA($uri);
 
index 40310b9144efc6f31462bd3f04e8b1db8737f175..4d1a05665e46e35e8be54465d61afcada111cedb 100644 (file)
@@ -10,7 +10,7 @@ class HTMLPurifier_AttrTransform_BdoDir extends HTMLPurifier_AttrTransform
 
     public function transform($attr, $config, $context) {
         if (isset($attr['dir'])) return $attr;
-        $attr['dir'] = $config->get('Attr', 'DefaultTextDir');
+        $attr['dir'] = $config->get('Attr.DefaultTextDir');
         return $attr;
     }
 
index 25c9403c209344b54b0db62472ea9ca2ab4c1581..a219479a029d52b4ef4bd7b29c41c1ea7930420c 100644 (file)
@@ -15,21 +15,21 @@ class HTMLPurifier_AttrTransform_ImgRequired extends HTMLPurifier_AttrTransform
 
         $src = true;
         if (!isset($attr['src'])) {
-            if ($config->get('Core', 'RemoveInvalidImg')) return $attr;
-            $attr['src'] = $config->get('Attr', 'DefaultInvalidImage');
+            if ($config->get('Core.RemoveInvalidImg')) return $attr;
+            $attr['src'] = $config->get('Attr.DefaultInvalidImage');
             $src = false;
         }
 
         if (!isset($attr['alt'])) {
             if ($src) {
-                $alt = $config->get('Attr', 'DefaultImageAlt');
+                $alt = $config->get('Attr.DefaultImageAlt');
                 if ($alt === null) {
                     $attr['alt'] = basename($attr['src']);
                 } else {
                     $attr['alt'] = $alt;
                 }
             } else {
-                $attr['alt'] = $config->get('Attr', 'DefaultInvalidImageAlt');
+                $attr['alt'] = $config->get('Attr.DefaultInvalidImageAlt');
             }
         }
 
index e6f93aee3bd41526588b611c527224254c708737..15315bc7353a4ef8801a53671654b2a3dde1d4b1 100644 (file)
@@ -7,6 +7,8 @@ class HTMLPurifier_AttrTransform_Name extends HTMLPurifier_AttrTransform
 {
 
     public function transform($attr, $config, $context) {
+        // Abort early if we're using relaxed definition of name
+        if ($config->get('HTML.Attr.Name.UseCDATA')) return $attr;
         if (!isset($attr['name'])) return $attr;
         $id = $this->confiscateAttr($attr, 'name');
         if ( isset($attr['id']))   return $attr;
diff --git a/lib/htmlpurifier/HTMLPurifier/AttrTransform/NameSync.php b/lib/htmlpurifier/HTMLPurifier/AttrTransform/NameSync.php
new file mode 100644 (file)
index 0000000..a95638c
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * Post-transform that performs validation to the name attribute; if
+ * it is present with an equivalent id attribute, it is passed through;
+ * otherwise validation is performed.
+ */
+class HTMLPurifier_AttrTransform_NameSync extends HTMLPurifier_AttrTransform
+{
+
+    public function __construct() {
+        $this->idDef = new HTMLPurifier_AttrDef_HTML_ID();
+    }
+
+    public function transform($attr, $config, $context) {
+        if (!isset($attr['name'])) return $attr;
+        $name = $attr['name'];
+        if (isset($attr['id']) && $attr['id'] === $name) return $attr;
+        $result = $this->idDef->validate($name, $config, $context);
+        if ($result === false) unset($attr['name']);
+        else $attr['name'] = $result;
+        return $attr;
+    }
+
+}
+
+// vim: et sw=4 sts=4
index 6c624bb0ba6dc801d5212abe4088e2f0fd4e412e..fc2ea4e5881bfc301db5fc7fcd9cd1aae9082932 100644 (file)
@@ -36,6 +36,9 @@ class HTMLPurifier_AttrTypes
         $this->info['Charsets'] = new HTMLPurifier_AttrDef_Text();
         $this->info['Character'] = new HTMLPurifier_AttrDef_Text();
 
+        // "proprietary" types
+        $this->info['Class'] = new HTMLPurifier_AttrDef_HTML_Class();
+
         // number is really a positive integer (one or more digits)
         // FIXME: ^^ not always, see start and value of list items
         $this->info['Number']   = new HTMLPurifier_AttrDef_Integer(false, false, true);
index 1a1805733864381d11e99e52463a03eef1dca084..6a2e6f56d99472283e575b05f54820cb1c88baba 100644 (file)
@@ -154,7 +154,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
             new HTMLPurifier_AttrDef_CSS_Percentage(true),
             new HTMLPurifier_AttrDef_Enum(array('auto'))
         ));
-        $max = $config->get('CSS', 'MaxImgLength');
+        $max = $config->get('CSS.MaxImgLength');
 
         $this->info['width'] =
         $this->info['height'] =
@@ -211,15 +211,15 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
         // partial support
         $this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(array('nowrap'));
 
-        if ($config->get('CSS', 'Proprietary')) {
+        if ($config->get('CSS.Proprietary')) {
             $this->doSetupProprietary($config);
         }
 
-        if ($config->get('CSS', 'AllowTricky')) {
+        if ($config->get('CSS.AllowTricky')) {
             $this->doSetupTricky($config);
         }
 
-        $allow_important = $config->get('CSS', 'AllowImportant');
+        $allow_important = $config->get('CSS.AllowImportant');
         // wrap all attr-defs with decorator that handles !important
         foreach ($this->info as $k => $v) {
             $this->info[$k] = new HTMLPurifier_AttrDef_CSS_ImportantDecorator($v, $allow_important);
@@ -272,7 +272,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
         // setup allowed elements
         $support = "(for information on implementing this, see the ".
                    "support forums) ";
-        $allowed_attributes = $config->get('CSS', 'AllowedProperties');
+        $allowed_attributes = $config->get('CSS.AllowedProperties');
         if ($allowed_attributes !== null) {
             foreach ($this->info as $name => $d) {
                 if(!isset($allowed_attributes[$name])) unset($this->info[$name]);
index c3e748b2601038486b2383dd4e9803a0239cdffe..4889f249b8629fc71460f344e4fa8deb30d1d22f 100644 (file)
@@ -59,7 +59,7 @@ class HTMLPurifier_ChildDef_Required extends HTMLPurifier_ChildDef
         $all_whitespace = true;
 
         // some configuration
-        $escape_invalid_children = $config->get('Core', 'EscapeInvalidChildren');
+        $escape_invalid_children = $config->get('Core.EscapeInvalidChildren');
 
         // generator
         $gen = new HTMLPurifier_Generator($config, $context);
index f8e1f7804ea688b9976cc3776ca97a361c3ee596..a01706043adf8a2d471a27ad480ce46eee8101d9 100644 (file)
@@ -20,7 +20,7 @@ class HTMLPurifier_Config
     /**
      * HTML Purifier's version
      */
-    public $version = '3.3.0';
+    public $version = '4.0.0';
 
     /**
      * Bool indicator whether or not to automatically finalize
@@ -68,12 +68,30 @@ class HTMLPurifier_Config
      */
     protected $plist;
 
+    /**
+     * Whether or not a set is taking place due to an
+     * alias lookup.
+     */
+    private $aliasMode;
+
+    /**
+     * Set to false if you do not want line and file numbers in errors
+     * (useful when unit testing)
+     */
+    public $chatty = true;
+
+    /**
+     * Current lock; only gets to this namespace are allowed.
+     */
+    private $lock;
+
     /**
      * @param $definition HTMLPurifier_ConfigSchema that defines what directives
      *                    are allowed.
      */
-    public function __construct($definition) {
-        $this->plist = new HTMLPurifier_PropertyList($definition->defaultPlist);
+    public function __construct($definition, $parent = null) {
+        $parent = $parent ? $parent : $definition->defaultPlist;
+        $this->plist = new HTMLPurifier_PropertyList($parent);
         $this->def = $definition; // keep a copy around for checking
         $this->parser = new HTMLPurifier_VarParser_Flexible();
     }
@@ -102,6 +120,16 @@ class HTMLPurifier_Config
         return $ret;
     }
 
+    /**
+     * Creates a new config object that inherits from a previous one.
+     * @param HTMLPurifier_Config $config Configuration object to inherit
+     *        from.
+     * @return HTMLPurifier_Config object with $config as its parent.
+     */
+    public static function inherit(HTMLPurifier_Config $config) {
+        return new HTMLPurifier_Config($config->def, $config->plist);
+    }
+
     /**
      * Convenience constructor that creates a default configuration object.
      * @return Default HTMLPurifier_Config object.
@@ -114,24 +142,34 @@ class HTMLPurifier_Config
 
     /**
      * Retreives a value from the configuration.
-     * @param $namespace String namespace
      * @param $key String key
      */
-    public function get($namespace, $key) {
-        if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true);
-        if (!isset($this->def->info[$namespace][$key])) {
+    public function get($key, $a = null) {
+        if ($a !== null) {
+            $this->triggerError("Using deprecated API: use \$config->get('$key.$a') instead", E_USER_WARNING);
+            $key = "$key.$a";
+        }
+        if (!$this->finalized) $this->autoFinalize();
+        if (!isset($this->def->info[$key])) {
             // can't add % due to SimpleTest bug
-            trigger_error('Cannot retrieve value of undefined directive ' . htmlspecialchars("$namespace.$key"),
+            $this->triggerError('Cannot retrieve value of undefined directive ' . htmlspecialchars($key),
                 E_USER_WARNING);
             return;
         }
-        if (isset($this->def->info[$namespace][$key]->isAlias)) {
-            $d = $this->def->info[$namespace][$key];
-            trigger_error('Cannot get value from aliased directive, use real name ' . $d->namespace . '.' . $d->name,
+        if (isset($this->def->info[$key]->isAlias)) {
+            $d = $this->def->info[$key];
+            $this->triggerError('Cannot get value from aliased directive, use real name ' . $d->key,
                 E_USER_ERROR);
             return;
         }
-        return $this->plist->get("$namespace.$key");
+        if ($this->lock) {
+            list($ns) = explode('.', $key);
+            if ($ns !== $this->lock) {
+                $this->triggerError('Cannot get value of namespace ' . $ns . ' when lock for ' . $this->lock . ' is active, this probably indicates a Definition setup method is accessing directives that are not within its namespace', E_USER_ERROR);
+                return;
+            }
+        }
+        return $this->plist->get($key);
     }
 
     /**
@@ -139,13 +177,13 @@ class HTMLPurifier_Config
      * @param $namespace String namespace
      */
     public function getBatch($namespace) {
-        if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true);
-        if (!isset($this->def->info[$namespace])) {
-            trigger_error('Cannot retrieve undefined namespace ' . htmlspecialchars($namespace),
+        if (!$this->finalized) $this->autoFinalize();
+        $full = $this->getAll();
+        if (!isset($full[$namespace])) {
+            $this->triggerError('Cannot retrieve undefined namespace ' . htmlspecialchars($namespace),
                 E_USER_WARNING);
             return;
         }
-        $full = $this->getAll();
         return $full[$namespace];
     }
 
@@ -178,9 +216,10 @@ class HTMLPurifier_Config
 
     /**
      * Retrieves all directives, organized by namespace
+     * @warning This is a pretty inefficient function, avoid if you can
      */
     public function getAll() {
-        if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true);
+        if (!$this->finalized) $this->autoFinalize();
         $ret = array();
         foreach ($this->plist->squash() as $name => $value) {
             list($ns, $key) = explode('.', $name, 2);
@@ -191,29 +230,37 @@ class HTMLPurifier_Config
 
     /**
      * Sets a value to configuration.
-     * @param $namespace String namespace
      * @param $key String key
      * @param $value Mixed value
      */
-    public function set($namespace, $key, $value, $from_alias = false) {
+    public function set($key, $value, $a = null) {
+        if (strpos($key, '.') === false) {
+            $namespace = $key;
+            $directive = $value;
+            $value = $a;
+            $key = "$key.$directive";
+            $this->triggerError("Using deprecated API: use \$config->set('$key', ...) instead", E_USER_NOTICE);
+        } else {
+            list($namespace) = explode('.', $key);
+        }
         if ($this->isFinalized('Cannot set directive after finalization')) return;
-        if (!isset($this->def->info[$namespace][$key])) {
-            trigger_error('Cannot set undefined directive ' . htmlspecialchars("$namespace.$key") . ' to value',
+        if (!isset($this->def->info[$key])) {
+            $this->triggerError('Cannot set undefined directive ' . htmlspecialchars($key) . ' to value',
                 E_USER_WARNING);
             return;
         }
-        $def = $this->def->info[$namespace][$key];
+        $def = $this->def->info[$key];
 
         if (isset($def->isAlias)) {
-            if ($from_alias) {
-                trigger_error('Double-aliases not allowed, please fix '.
-                    'ConfigSchema bug with' . "$namespace.$key", E_USER_ERROR);
+            if ($this->aliasMode) {
+                $this->triggerError('Double-aliases not allowed, please fix '.
+                    'ConfigSchema bug with' . $key, E_USER_ERROR);
                 return;
             }
-            $this->set($new_ns  = $def->namespace,
-                       $new_dir = $def->name,
-                       $value, true);
-            trigger_error("$namespace.$key is an alias, preferred directive name is $new_ns.$new_dir", E_USER_NOTICE);
+            $this->aliasMode = true;
+            $this->set($def->key, $value);
+            $this->aliasMode = false;
+            $this->triggerError("$key is an alias, preferred directive name is {$def->key}", E_USER_NOTICE);
             return;
         }
 
@@ -231,7 +278,7 @@ class HTMLPurifier_Config
         try {
             $value = $this->parser->parse($value, $type, $allow_null);
         } catch (HTMLPurifier_VarParserException $e) {
-            trigger_error('Value for ' . "$namespace.$key" . ' is of invalid type, should be ' . HTMLPurifier_VarParser::getTypeName($type), E_USER_WARNING);
+            $this->triggerError('Value for ' . $key . ' is of invalid type, should be ' . HTMLPurifier_VarParser::getTypeName($type), E_USER_WARNING);
             return;
         }
         if (is_string($value) && is_object($def)) {
@@ -241,17 +288,17 @@ class HTMLPurifier_Config
             }
             // check to see if the value is allowed
             if (isset($def->allowed) && !isset($def->allowed[$value])) {
-                trigger_error('Value not supported, valid values are: ' .
+                $this->triggerError('Value not supported, valid values are: ' .
                     $this->_listify($def->allowed), E_USER_WARNING);
                 return;
             }
         }
-        $this->plist->set("$namespace.$key", $value);
+        $this->plist->set($key, $value);
 
         // reset definitions if the directives they depend on changed
         // this is a very costly process, so it's discouraged
         // with finalization
-        if ($namespace == 'HTML' || $namespace == 'CSS') {
+        if ($namespace == 'HTML' || $namespace == 'CSS' || $namespace == 'URI') {
             $this->definitions[$namespace] = null;
         }
 
@@ -291,9 +338,13 @@ class HTMLPurifier_Config
      * @param $raw  Whether or not definition should be returned raw
      */
     public function getDefinition($type, $raw = false) {
-        if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true);
+        if (!$this->finalized) $this->autoFinalize();
+        // temporarily suspend locks, so we can handle recursive definition calls
+        $lock = $this->lock;
+        $this->lock = null;
         $factory = HTMLPurifier_DefinitionCacheFactory::instance();
         $cache = $factory->create($type, $this);
+        $this->lock = $lock;
         if (!$raw) {
             // see if we can quickly supply a definition
             if (!empty($this->definitions[$type])) {
@@ -328,14 +379,16 @@ class HTMLPurifier_Config
         }
         // quick abort if raw
         if ($raw) {
-            if (is_null($this->get($type, 'DefinitionID'))) {
+            if (is_null($this->get($type . '.DefinitionID'))) {
                 // fatally error out if definition ID not set
                 throw new HTMLPurifier_Exception("Cannot retrieve raw version without specifying %$type.DefinitionID");
             }
             return $this->definitions[$type];
         }
         // set it up
+        $this->lock = $type;
         $this->definitions[$type]->setup($this);
+        $this->lock = null;
         // save in cache
         $cache->set($this->definitions[$type], $this);
         return $this->definitions[$type];
@@ -351,14 +404,12 @@ class HTMLPurifier_Config
         foreach ($config_array as $key => $value) {
             $key = str_replace('_', '.', $key);
             if (strpos($key, '.') !== false) {
-                // condensed form
-                list($namespace, $directive) = explode('.', $key);
-                $this->set($namespace, $directive, $value);
+                $this->set($key, $value);
             } else {
                 $namespace = $key;
                 $namespace_values = $value;
                 foreach ($namespace_values as $directive => $value) {
-                    $this->set($namespace, $directive, $value);
+                    $this->set($namespace .'.'. $directive, $value);
                 }
             }
         }
@@ -394,16 +445,15 @@ class HTMLPurifier_Config
              }
         }
         $ret = array();
-        foreach ($schema->info as $ns => $keypairs) {
-            foreach ($keypairs as $directive => $def) {
-                if ($allowed !== true) {
-                    if (isset($blacklisted_directives["$ns.$directive"])) continue;
-                    if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) continue;
-                }
-                if (isset($def->isAlias)) continue;
-                if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') continue;
-                $ret[] = array($ns, $directive);
+        foreach ($schema->info as $key => $def) {
+            list($ns, $directive) = explode('.', $key, 2);
+            if ($allowed !== true) {
+                if (isset($blacklisted_directives["$ns.$directive"])) continue;
+                if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) continue;
             }
+            if (isset($def->isAlias)) continue;
+            if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') continue;
+            $ret[] = array($ns, $directive);
         }
         return $ret;
     }
@@ -472,7 +522,7 @@ class HTMLPurifier_Config
      */
     public function isFinalized($error = false) {
         if ($this->finalized && $error) {
-            trigger_error($error, E_USER_ERROR);
+            $this->triggerError($error, E_USER_ERROR);
         }
         return $this->finalized;
     }
@@ -482,7 +532,11 @@ class HTMLPurifier_Config
      * already finalized
      */
     public function autoFinalize() {
-        if (!$this->finalized && $this->autoFinalize) $this->finalize();
+        if ($this->autoFinalize) {
+            $this->finalize();
+        } else {
+            $this->plist->squash(true);
+        }
     }
 
     /**
@@ -490,6 +544,35 @@ class HTMLPurifier_Config
      */
     public function finalize() {
         $this->finalized = true;
+        unset($this->parser);
+    }
+
+    /**
+     * Produces a nicely formatted error message by supplying the
+     * stack frame information from two levels up and OUTSIDE of
+     * HTMLPurifier_Config.
+     */
+    protected function triggerError($msg, $no) {
+        // determine previous stack frame
+        $backtrace = debug_backtrace();
+        if ($this->chatty && isset($backtrace[1])) {
+            $frame = $backtrace[1];
+            $extra = " on line {$frame['line']} in file {$frame['file']}";
+        } else {
+            $extra = '';
+        }
+        trigger_error($msg . $extra, $no);
+    }
+
+    /**
+     * Returns a serialized form of the configuration object that can
+     * be reconstituted.
+     */
+    public function serialize() {
+        $this->getDefinition('HTML');
+        $this->getDefinition('CSS');
+        $this->getDefinition('URI');
+        return serialize($this);
     }
 
 }
index 340ed7dbc67bf571767fc3beede44a1ff6b6882c..67be5c71fd8984451d2fb6dd40aca0695b4daa6d 100644 (file)
@@ -87,24 +87,13 @@ class HTMLPurifier_ConfigSchema {
      *      HTMLPurifier_DirectiveDef::$type for allowed values
      * @param $allow_null Whether or not to allow null values
      */
-    public function add($namespace, $name, $default, $type, $allow_null) {
+    public function add($key, $default, $type, $allow_null) {
         $obj = new stdclass();
         $obj->type = is_int($type) ? $type : HTMLPurifier_VarParser::$types[$type];
         if ($allow_null) $obj->allow_null = true;
-        $this->info[$namespace][$name] = $obj;
-        $this->defaults[$namespace][$name] = $default;
-        $this->defaultPlist->set("$namespace.$name", $default);
-    }
-
-    /**
-     * Defines a namespace for directives to be put into.
-     * @warning This is slightly different from the corresponding static
-     *          method.
-     * @param $namespace Namespace's name
-     */
-    public function addNamespace($namespace) {
-        $this->info[$namespace] = array();
-        $this->defaults[$namespace] = array();
+        $this->info[$key] = $obj;
+        $this->defaults[$key] = $default;
+        $this->defaultPlist->set($key, $default);
     }
 
     /**
@@ -116,12 +105,12 @@ class HTMLPurifier_ConfigSchema {
      * @param $name Name of Directive
      * @param $aliases Hash of aliased values to the real alias
      */
-    public function addValueAliases($namespace, $name, $aliases) {
-        if (!isset($this->info[$namespace][$name]->aliases)) {
-            $this->info[$namespace][$name]->aliases = array();
+    public function addValueAliases($key, $aliases) {
+        if (!isset($this->info[$key]->aliases)) {
+            $this->info[$key]->aliases = array();
         }
         foreach ($aliases as $alias => $real) {
-            $this->info[$namespace][$name]->aliases[$alias] = $real;
+            $this->info[$key]->aliases[$alias] = $real;
         }
     }
 
@@ -133,8 +122,8 @@ class HTMLPurifier_ConfigSchema {
      * @param $name Name of directive
      * @param $allowed Lookup array of allowed values
      */
-    public function addAllowedValues($namespace, $name, $allowed) {
-        $this->info[$namespace][$name]->allowed = $allowed;
+    public function addAllowedValues($key, $allowed) {
+        $this->info[$key]->allowed = $allowed;
     }
 
     /**
@@ -144,88 +133,26 @@ class HTMLPurifier_ConfigSchema {
      * @param $new_namespace
      * @param $new_name Directive that the alias will be to
      */
-    public function addAlias($namespace, $name, $new_namespace, $new_name) {
+    public function addAlias($key, $new_key) {
         $obj = new stdclass;
-        $obj->namespace = $new_namespace;
-        $obj->name = $new_name;
+        $obj->key = $new_key;
         $obj->isAlias = true;
-        $this->info[$namespace][$name] = $obj;
+        $this->info[$key] = $obj;
     }
 
     /**
      * Replaces any stdclass that only has the type property with type integer.
      */
     public function postProcess() {
-        foreach ($this->info as $namespace => $info) {
-            foreach ($info as $directive => $v) {
-                if (count((array) $v) == 1) {
-                    $this->info[$namespace][$directive] = $v->type;
-                } elseif (count((array) $v) == 2 && isset($v->allow_null)) {
-                    $this->info[$namespace][$directive] = -$v->type;
-                }
+        foreach ($this->info as $key => $v) {
+            if (count((array) $v) == 1) {
+                $this->info[$key] = $v->type;
+            } elseif (count((array) $v) == 2 && isset($v->allow_null)) {
+                $this->info[$key] = -$v->type;
             }
         }
     }
 
-    // DEPRECATED METHODS
-
-    /** @see HTMLPurifier_ConfigSchema->set() */
-    public static function define($namespace, $name, $default, $type, $description) {
-        HTMLPurifier_ConfigSchema::deprecated(__METHOD__);
-        $type_values = explode('/', $type, 2);
-        $type = $type_values[0];
-        $modifier = isset($type_values[1]) ? $type_values[1] : false;
-        $allow_null = ($modifier === 'null');
-        $def = HTMLPurifier_ConfigSchema::instance();
-        $def->add($namespace, $name, $default, $type, $allow_null);
-    }
-
-    /** @see HTMLPurifier_ConfigSchema->addNamespace() */
-    public static function defineNamespace($namespace, $description) {
-        HTMLPurifier_ConfigSchema::deprecated(__METHOD__);
-        $def = HTMLPurifier_ConfigSchema::instance();
-        $def->addNamespace($namespace);
-    }
-
-    /** @see HTMLPurifier_ConfigSchema->addValueAliases() */
-    public static function defineValueAliases($namespace, $name, $aliases) {
-        HTMLPurifier_ConfigSchema::deprecated(__METHOD__);
-        $def = HTMLPurifier_ConfigSchema::instance();
-        $def->addValueAliases($namespace, $name, $aliases);
-    }
-
-    /** @see HTMLPurifier_ConfigSchema->addAllowedValues() */
-    public static function defineAllowedValues($namespace, $name, $allowed_values) {
-        HTMLPurifier_ConfigSchema::deprecated(__METHOD__);
-        $allowed = array();
-        foreach ($allowed_values as $value) {
-            $allowed[$value] = true;
-        }
-        $def = HTMLPurifier_ConfigSchema::instance();
-        $def->addAllowedValues($namespace, $name, $allowed);
-    }
-
-    /** @see HTMLPurifier_ConfigSchema->addAlias() */
-    public static function defineAlias($namespace, $name, $new_namespace, $new_name) {
-        HTMLPurifier_ConfigSchema::deprecated(__METHOD__);
-        $def = HTMLPurifier_ConfigSchema::instance();
-        $def->addAlias($namespace, $name, $new_namespace, $new_name);
-    }
-
-    /** @deprecated, use HTMLPurifier_VarParser->parse() */
-    public function validate($a, $b, $c = false) {
-        trigger_error("HTMLPurifier_ConfigSchema->validate deprecated, use HTMLPurifier_VarParser->parse instead", E_USER_NOTICE);
-        $parser = new HTMLPurifier_VarParser();
-        return $parser->parse($a, $b, $c);
-    }
-
-    /**
-     * Throws an E_USER_NOTICE stating that a method is deprecated.
-     */
-    private static function deprecated($method) {
-        trigger_error("Static HTMLPurifier_ConfigSchema::$method deprecated, use add*() method instead", E_USER_NOTICE);
-    }
-
 }
 
 // vim: et sw=4 sts=4
index 987f547bcaffcc1976517dfd21339ed3ecd4a3ac..c05668a7060398c870e25b19debe75325de84323 100644 (file)
@@ -9,36 +9,28 @@ class HTMLPurifier_ConfigSchema_Builder_ConfigSchema
 
     public function build($interchange) {
         $schema = new HTMLPurifier_ConfigSchema();
-        foreach ($interchange->namespaces as $n) {
-            $schema->addNamespace($n->namespace);
-        }
         foreach ($interchange->directives as $d) {
             $schema->add(
-                $d->id->namespace,
-                $d->id->directive,
+                $d->id->key,
                 $d->default,
                 $d->type,
                 $d->typeAllowsNull
             );
             if ($d->allowed !== null) {
                 $schema->addAllowedValues(
-                    $d->id->namespace,
-                    $d->id->directive,
+                    $d->id->key,
                     $d->allowed
                 );
             }
             foreach ($d->aliases as $alias) {
                 $schema->addAlias(
-                    $alias->namespace,
-                    $alias->directive,
-                    $d->id->namespace,
-                    $d->id->directive
+                    $alias->key,
+                    $d->id->key
                 );
             }
             if ($d->valueAliases !== null) {
                 $schema->addValueAliases(
-                    $d->id->namespace,
-                    $d->id->directive,
+                    $d->id->key,
                     $d->valueAliases
                 );
             }
index 51bcab78cc4951e0c63548bd28890447a40b2e4d..244561a3726dc8581ca4e13351f22a261dae29c1 100644 (file)
@@ -8,6 +8,7 @@ class HTMLPurifier_ConfigSchema_Builder_Xml extends XMLWriter
 {
 
     protected $interchange;
+    private $namespace;
 
     protected function writeHTMLDiv($html) {
         $this->startElement('div');
@@ -34,36 +35,33 @@ class HTMLPurifier_ConfigSchema_Builder_Xml extends XMLWriter
         $this->startElement('configdoc');
         $this->writeElement('title', $interchange->name);
 
-        foreach ($interchange->namespaces as $namespace) {
-            $this->buildNamespace($namespace);
+        foreach ($interchange->directives as $directive) {
+            $this->buildDirective($directive);
         }
 
+        if ($this->namespace) $this->endElement(); // namespace
+
         $this->endElement(); // configdoc
         $this->flush();
     }
 
-    public function buildNamespace($namespace) {
-        $this->startElement('namespace');
-        $this->writeAttribute('id', $namespace->namespace);
-
-        $this->writeElement('name', $namespace->namespace);
-        $this->startElement('description');
-            $this->writeHTMLDiv($namespace->description);
-        $this->endElement(); // description
+    public function buildDirective($directive) {
 
-        foreach ($this->interchange->directives as $directive) {
-            if ($directive->id->namespace !== $namespace->namespace) continue;
-            $this->buildDirective($directive);
+        // Kludge, although I suppose having a notion of a "root namespace"
+        // certainly makes things look nicer when documentation is built.
+        // Depends on things being sorted.
+        if (!$this->namespace || $this->namespace !== $directive->id->getRootNamespace()) {
+            if ($this->namespace) $this->endElement(); // namespace
+            $this->namespace = $directive->id->getRootNamespace();
+            $this->startElement('namespace');
+            $this->writeAttribute('id', $this->namespace);
+            $this->writeElement('name', $this->namespace);
         }
 
-        $this->endElement(); // namespace
-    }
-
-    public function buildDirective($directive) {
         $this->startElement('directive');
         $this->writeAttribute('id', $directive->id->toString());
 
-        $this->writeElement('name', $directive->id->directive);
+        $this->writeElement('name', $directive->id->getDirective());
 
         $this->startElement('aliases');
             foreach ($directive->aliases as $alias) $this->writeElement('alias', $alias->toString());
index 365c66357f55430b11f8220219a6fb9de939e44b..91a5aa7303f0582dc55cd351d36fe241162ce786 100644 (file)
@@ -13,26 +13,11 @@ class HTMLPurifier_ConfigSchema_Interchange
      */
     public $name;
 
-    /**
-     * Array of Namespace ID => array(namespace info)
-     */
-    public $namespaces = array();
-
     /**
      * Array of Directive ID => array(directive info)
      */
     public $directives = array();
 
-    /**
-     * Adds a namespace array to $namespaces
-     */
-    public function addNamespace($namespace) {
-        if (isset($this->namespaces[$i = $namespace->namespace])) {
-            throw new HTMLPurifier_ConfigSchema_Exception("Cannot redefine namespace '$i'");
-        }
-        $this->namespaces[$i] = $namespace;
-    }
-
     /**
      * Adds a directive array to $directives
      */
index ec01589b623a1262c28b1b76283873b33d68e8f2..b9b3c6f5cfbdd0819a34579e857f2e724dcb4edc 100644 (file)
@@ -6,11 +6,10 @@
 class HTMLPurifier_ConfigSchema_Interchange_Id
 {
 
-    public $namespace, $directive;
+    public $key;
 
-    public function __construct($namespace, $directive) {
-        $this->namespace = $namespace;
-        $this->directive = $directive;
+    public function __construct($key) {
+        $this->key = $key;
     }
 
     /**
@@ -18,12 +17,19 @@ class HTMLPurifier_ConfigSchema_Interchange_Id
      *          cause problems for PHP 5.0 support.
      */
     public function toString() {
-        return $this->namespace . '.' . $this->directive;
+        return $this->key;
+    }
+
+    public function getRootNamespace() {
+        return substr($this->key, 0, strpos($this->key, "."));
+    }
+
+    public function getDirective() {
+        return substr($this->key, strpos($this->key, ".") + 1);
     }
 
     public static function make($id) {
-        list($namespace, $directive) = explode('.', $id);
-        return new HTMLPurifier_ConfigSchema_Interchange_Id($namespace, $directive);
+        return new HTMLPurifier_ConfigSchema_Interchange_Id($id);
     }
 
 }
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/Interchange/Namespace.php b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/Interchange/Namespace.php
deleted file mode 100644 (file)
index 3ffac0a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-/**
- * Interchange component class describing namespaces.
- */
-class HTMLPurifier_ConfigSchema_Interchange_Namespace
-{
-
-    /**
-     * Name of namespace defined.
-     */
-    public $namespace;
-
-    /**
-     * HTML description.
-     */
-    public $description;
-
-}
-
-// vim: et sw=4 sts=4
index a1a24eacbaffa1dd455b31926ea29906e337241b..785b72ce8e93d151465f293b351a4c9455c0e1d4 100644 (file)
@@ -13,13 +13,17 @@ class HTMLPurifier_ConfigSchema_InterchangeBuilder
     }
 
     public static function buildFromDirectory($dir = null) {
-        $parser      = new HTMLPurifier_StringHashParser();
         $builder     = new HTMLPurifier_ConfigSchema_InterchangeBuilder();
         $interchange = new HTMLPurifier_ConfigSchema_Interchange();
+        return $builder->buildDir($interchange, $dir);
+    }
 
-        if (!$dir) $dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema/';
-        $info = parse_ini_file($dir . 'info.ini');
-        $interchange->name = $info['name'];
+    public function buildDir($interchange, $dir = null) {
+        if (!$dir) $dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema';
+        if (file_exists($dir . '/info.ini')) {
+            $info = parse_ini_file($dir . '/info.ini');
+            $interchange->name = $info['name'];
+        }
 
         $files = array();
         $dh = opendir($dir);
@@ -33,15 +37,20 @@ class HTMLPurifier_ConfigSchema_InterchangeBuilder
 
         sort($files);
         foreach ($files as $file) {
-            $builder->build(
-                $interchange,
-                new HTMLPurifier_StringHash( $parser->parseFile($dir . $file) )
-            );
+            $this->buildFile($interchange, $dir . '/' . $file);
         }
 
         return $interchange;
     }
 
+    public function buildFile($interchange, $file) {
+        $parser = new HTMLPurifier_StringHashParser();
+        $this->build(
+            $interchange,
+            new HTMLPurifier_StringHash( $parser->parseFile($file) )
+        );
+    }
+
     /**
      * Builds an interchange object based on a hash.
      * @param $interchange HTMLPurifier_ConfigSchema_Interchange object to build
@@ -55,22 +64,17 @@ class HTMLPurifier_ConfigSchema_InterchangeBuilder
             throw new HTMLPurifier_ConfigSchema_Exception('Hash does not have any ID');
         }
         if (strpos($hash['ID'], '.') === false) {
-            $this->buildNamespace($interchange, $hash);
+            if (count($hash) == 2 && isset($hash['DESCRIPTION'])) {
+                $hash->offsetGet('DESCRIPTION'); // prevent complaining
+            } else {
+                throw new HTMLPurifier_ConfigSchema_Exception('All directives must have a namespace');
+            }
         } else {
             $this->buildDirective($interchange, $hash);
         }
         $this->_findUnused($hash);
     }
 
-    public function buildNamespace($interchange, $hash) {
-        $namespace = new HTMLPurifier_ConfigSchema_Interchange_Namespace();
-        $namespace->namespace   = $hash->offsetGet('ID');
-        if (isset($hash['DESCRIPTION'])) {
-            $namespace->description = $hash->offsetGet('DESCRIPTION');
-        }
-        $interchange->addNamespace($namespace);
-    }
-
     public function buildDirective($interchange, $hash) {
         $directive = new HTMLPurifier_ConfigSchema_Interchange_Directive();
 
index 2dfd37baed8bc9809883a753fc38b76d678f8dd2..f374f6a02259f8fae5303d3f794c74b5b6461a99 100644 (file)
@@ -39,10 +39,6 @@ class HTMLPurifier_ConfigSchema_Validator
         $this->aliases = array();
         // PHP is a bit lax with integer <=> string conversions in
         // arrays, so we don't use the identical !== comparison
-        foreach ($interchange->namespaces as $i => $namespace) {
-            if ($i != $namespace->namespace) $this->error(false, "Integrity violation: key '$i' does not match internal id '{$namespace->namespace}'");
-            $this->validateNamespace($namespace);
-        }
         foreach ($interchange->directives as $i => $directive) {
             $id = $directive->id->toString();
             if ($i != $id) $this->error(false, "Integrity violation: key '$i' does not match internal id '$id'");
@@ -51,20 +47,6 @@ class HTMLPurifier_ConfigSchema_Validator
         return true;
     }
 
-    /**
-     * Validates a HTMLPurifier_ConfigSchema_Interchange_Namespace object.
-     */
-    public function validateNamespace($n) {
-        $this->context[] = "namespace '{$n->namespace}'";
-        $this->with($n, 'namespace')
-            ->assertNotEmpty()
-            ->assertAlnum(); // implicit assertIsString handled by InterchangeBuilder
-        $this->with($n, 'description')
-            ->assertNotEmpty()
-            ->assertIsString(); // handled by InterchangeBuilder
-        array_pop($this->context);
-    }
-
     /**
      * Validates a HTMLPurifier_ConfigSchema_Interchange_Id object.
      */
@@ -75,12 +57,11 @@ class HTMLPurifier_ConfigSchema_Validator
             // handled by InterchangeBuilder
             $this->error(false, 'is not an instance of HTMLPurifier_ConfigSchema_Interchange_Id');
         }
-        if (!isset($this->interchange->namespaces[$id->namespace])) {
-            $this->error('namespace', 'does not exist'); // assumes that the namespace was validated already
-        }
-        $this->with($id, 'directive')
+        // keys are now unconstrained (we might want to narrow down to A-Za-z0-9.)
+        // we probably should check that it has at least one namespace
+        $this->with($id, 'key')
             ->assertNotEmpty()
-            ->assertAlnum(); // implicit assertIsString handled by InterchangeBuilder
+            ->assertIsString(); // implicit assertIsString handled by InterchangeBuilder
         array_pop($this->context);
     }
 
index 1eaecd11f856504cde09c1b302c7c1cfd65ec00b..bbf12f9c3e7392aa8143727d2485f6f9ad1f97e1 100644 (file)
Binary files a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema.ser and b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema.ser differ
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt
new file mode 100644 (file)
index 0000000..0517fed
--- /dev/null
@@ -0,0 +1,8 @@
+Attr.AllowedClasses
+TYPE: lookup/null
+VERSION: 4.0.0
+DEFAULT: null
+--DESCRIPTION--
+List of allowed class values in the class attribute. By default, this is null,
+which means all classes are allowed.
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt
new file mode 100644 (file)
index 0000000..e774b82
--- /dev/null
@@ -0,0 +1,19 @@
+Attr.ClassUseCDATA
+TYPE: bool/null
+DEFAULT: null
+VERSION: 4.0.0
+--DESCRIPTION--
+If null, class will auto-detect the doctype and, if matching XHTML 1.1 or
+XHTML 2.0, will use the restrictive NMTOKENS specification of class. Otherwise,
+it will use a relaxed CDATA definition.  If true, the relaxed CDATA definition
+is forced; if false, the NMTOKENS definition is forced.  To get behavior
+of HTML Purifier prior to 4.0.0, set this directive to false.
+
+Some rational behind the auto-detection:
+in previous versions of HTML Purifier, it was assumed that the form of
+class was NMTOKENS, as specified by the XHTML Modularization (representing
+XHTML 1.1 and XHTML 2.0).  The DTDs for HTML 4.01 and XHTML 1.0, however
+specify class as CDATA.  HTML 5 effectively defines it as CDATA, but
+with the additional constraint that each name should be unique (this is not
+explicitly outlined in previous specifications).
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt
new file mode 100644 (file)
index 0000000..f31d226
--- /dev/null
@@ -0,0 +1,8 @@
+Attr.ForbiddenClasses
+TYPE: lookup
+VERSION: 4.0.0
+DEFAULT: array()
+--DESCRIPTION--
+List of forbidden class values in the class attribute. By default, this is
+empty, which means that no classes are forbidden. See also %Attr.AllowedClasses.
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Attr.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Attr.txt
deleted file mode 100644 (file)
index 2d72049..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-Attr
-DESCRIPTION: Features regarding attribute validation.
---# vim: et sw=4 sts=4
similarity index 75%
rename from lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormatParam.PurifierLinkifyDocURL.txt
rename to lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt
index 3e8309e39e2b9832b2777f63ec9049ad0e3b961b..db58b134646b496cfa31c191e05f1fa52c8b7670 100644 (file)
@@ -1,9 +1,9 @@
-AutoFormatParam.PurifierLinkifyDocURL
+AutoFormat.PurifierLinkify.DocURL
 TYPE: string
 VERSION: 2.0.1
 DEFAULT: '#%s'
+ALIASES: AutoFormatParam.PurifierLinkifyDocURL
 --DESCRIPTION--
-
 <p>
   Location of configuration documentation to link to, let %s substitute
   into the configuration's namespace and directive names sans the percent
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt
new file mode 100644 (file)
index 0000000..35c393b
--- /dev/null
@@ -0,0 +1,11 @@
+AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions
+TYPE: lookup
+VERSION: 4.0.0
+DEFAULT: array('td' => true, 'th' => true)
+--DESCRIPTION--
+<p>
+  When %AutoFormat.RemoveEmpty and %AutoFormat.RemoveEmpty.RemoveNbsp
+  are enabled, this directive defines what HTML elements should not be
+  removede if they have only a non-breaking space in them.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt
new file mode 100644 (file)
index 0000000..ca17eb1
--- /dev/null
@@ -0,0 +1,15 @@
+AutoFormat.RemoveEmpty.RemoveNbsp
+TYPE: bool
+VERSION: 4.0.0
+DEFAULT: false
+--DESCRIPTION--
+<p>
+  When enabled, HTML Purifier will treat any elements that contain only
+  non-breaking spaces as well as regular whitespace as empty, and remove
+  them when %AutoForamt.RemoveEmpty is enabled.
+</p>
+<p>
+  See %AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions for a list of elements
+  that don't have this behavior applied to them.
+</p>
+--# vim: et sw=4 sts=4
index aaede47d62ffdd9c8d3b147b897b3e8283b927d6..34657ba47b15e7980ff2fcd80f7b2ad2807ef6ab 100644 (file)
@@ -31,7 +31,8 @@ DEFAULT: false
 </p>
 <p>
   Elements that contain only whitespace will be treated as empty. Non-breaking
-  spaces, however, do not count as whitespace.
+  spaces, however, do not count as whitespace. See
+  %AutoFormat.RemoveEmpty.RemoveNbsp for alternate behavior.
 </p>
 <p>
   This algorithm is not perfect; you may still notice some empty tags,
@@ -39,7 +40,7 @@ DEFAULT: false
   because they were not permitted in that context, or tags that, after
   being auto-closed by another tag, where empty. This is for safety reasons
   to prevent clever code from breaking validation. The general rule of thumb:
-  if a tag looked empty on the way end, it will get removed; if HTML Purifier
+  if a tag looked empty on the way in, it will get removed; if HTML Purifier
   made it empty, it will stay.
 </p>
 --# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.txt
deleted file mode 100644 (file)
index 161a52e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-AutoFormat
-DESCRIPTION: Configuration for activating auto-formatting functionality (also known as <code>Injector</code>s)
---# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormatParam.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormatParam.txt
deleted file mode 100644 (file)
index 6097a55..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-AutoFormatParam
-DESCRIPTION: Configuration for customizing auto-formatting functionality
---# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/CSS.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/CSS.txt
deleted file mode 100644 (file)
index d14b490..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-CSS
-DESCRIPTION: Configuration regarding allowed CSS.
---# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Cache.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Cache.txt
deleted file mode 100644 (file)
index 57f3023..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-Cache
-DESCRIPTION: Configuration for DefinitionCache and related subclasses.
---# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Core.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Core.txt
deleted file mode 100644 (file)
index 5edfe07..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-Core
-DESCRIPTION: Core features that are always available.
---# vim: et sw=4 sts=4
similarity index 75%
rename from lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/FilterParam.ExtractStyleBlocksEscaping.txt
rename to lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt
index d436ed015800084bc97a3b2d29aabfe78793c5e7..16829bcda0335f582c83ff6e2a603111e412700b 100644 (file)
@@ -1,8 +1,8 @@
-FilterParam.ExtractStyleBlocksEscaping
+Filter.ExtractStyleBlocks.Escaping
 TYPE: bool
 VERSION: 3.0.0
 DEFAULT: true
-ALIASES: Filter.ExtractStyleBlocksEscaping
+ALIASES: Filter.ExtractStyleBlocksEscaping, FilterParam.ExtractStyleBlocksEscaping
 --DESCRIPTION--
 
 <p>
similarity index 90%
rename from lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/FilterParam.ExtractStyleBlocksScope.txt
rename to lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt
index 3943529c7b09f61c7f3b9161276bc84d9af5ddd9..7f95f54d125de2312dc7bcd6630e453cee73bd5c 100644 (file)
@@ -1,8 +1,8 @@
-FilterParam.ExtractStyleBlocksScope
+Filter.ExtractStyleBlocks.Scope
 TYPE: string/null
 VERSION: 3.0.0
 DEFAULT: NULL
-ALIASES: Filter.ExtractStyleBlocksScope
+ALIASES: Filter.ExtractStyleBlocksScope, FilterParam.ExtractStyleBlocksScope
 --DESCRIPTION--
 
 <p>
similarity index 85%
rename from lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/FilterParam.ExtractStyleBlocksTidyImpl.txt
rename to lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt
index cafccf8b53cc220933587e1bbca05d80ca6e89fb..6c231b2d7f7b2a1ccb9fc90e0162b8f0396ae30d 100644 (file)
@@ -1,7 +1,8 @@
-FilterParam.ExtractStyleBlocksTidyImpl
+Filter.ExtractStyleBlocks.TidyImpl
 TYPE: mixed/null
 VERSION: 3.1.0
 DEFAULT: NULL
+ALIASES: FilterParam.ExtractStyleBlocksTidyImpl
 --DESCRIPTION--
 <p>
   If left NULL, HTML Purifier will attempt to instantiate a <code>csstidy</code>
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Filter.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Filter.txt
deleted file mode 100644 (file)
index f2d25a1..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-Filter
-DESCRIPTION: Directives for turning filters on and off, or specifying custom filters.
---# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/FilterParam.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/FilterParam.txt
deleted file mode 100644 (file)
index dff9784..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-FilterParam
-DESCRIPTION: Configuration for filters.
---# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt
new file mode 100644 (file)
index 0000000..151fb7b
--- /dev/null
@@ -0,0 +1,11 @@
+HTML.Attr.Name.UseCDATA
+TYPE: bool
+DEFAULT: false
+VERSION: 4.0.0
+--DESCRIPTION--
+The W3C specification DTD defines the name attribute to be CDATA, not ID, due
+to limitations of DTD.  In certain documents, this relaxed behavior is desired,
+whether it is to specify duplicate names, or to specify names that would be
+illegal IDs (for example, names that begin with a digit.) Set this configuration
+directive to true to use the relaxed parsing rules.
+--# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.txt
deleted file mode 100644 (file)
index f32ceb5..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-HTML
-DESCRIPTION: Configuration regarding allowed HTML.
---# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Output.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Output.txt
deleted file mode 100644 (file)
index 7849d60..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-Output
-DESCRIPTION: Configuration relating to the generation of (X)HTML.
---# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Test.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Test.txt
deleted file mode 100644 (file)
index 5025f9d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-Test
-DESCRIPTION: Developer testing configuration for our unit tests.
---# vim: et sw=4 sts=4
diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/URI.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/URI.txt
deleted file mode 100644 (file)
index a13060f..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-URI
-DESCRIPTION: Features regarding Uniform Resource Identifiers.
---# vim: et sw=4 sts=4
index fa5a087bb754b71c667746549a27e3386609ad91..c6e1e388c6513251112fcb4d911d14983298f79b 100644 (file)
@@ -28,7 +28,7 @@ abstract class HTMLPurifier_DefinitionCache
     public function generateKey($config) {
         return $config->version . ',' . // possibly replace with function calls
                $config->getBatchSerial($this->type) . ',' .
-               $config->get($this->type, 'DefinitionRev');
+               $config->get($this->type . '.DefinitionRev');
     }
 
     /**
@@ -46,7 +46,7 @@ abstract class HTMLPurifier_DefinitionCache
         // versions match, ids match, check revision number
         if (
             $hash == $config->getBatchSerial($this->type) &&
-            $revision < $config->get($this->type, 'DefinitionRev')
+            $revision < $config->get($this->type . '.DefinitionRev')
         ) return true;
         return false;
     }
index acbbe2c3b37f5c0766c717513ac59c01bc1680c0..7a6aa93f0290bec0ac18771b60e6a66fcb48ac46 100644 (file)
@@ -88,7 +88,7 @@ class HTMLPurifier_DefinitionCache_Serializer extends
      * @todo Make protected
      */
     public function generateBaseDirectoryPath($config) {
-        $base = $config->get('Cache', 'SerializerPath');
+        $base = $config->get('Cache.SerializerPath');
         $base = is_null($base) ? HTMLPURIFIER_PREFIX . '/HTMLPurifier/DefinitionCache/Serializer' : $base;
         return $base;
     }
index 3adefbb661c5d55df6fd403f9ba07b4a57187a09..a6ead62818754b90c0c3aca45cbf9f4cae5e0f86 100644 (file)
@@ -46,7 +46,7 @@ class HTMLPurifier_DefinitionCacheFactory
      * @param $config Instance of HTMLPurifier_Config
      */
     public function create($type, $config) {
-        $method = $config->get('Cache', 'DefinitionImpl');
+        $method = $config->get('Cache.DefinitionImpl');
         if ($method === null) {
             return new HTMLPurifier_DefinitionCache_Null($type);
         }
index d6552aa5503ecb2bb05715bdb9acf27b0a45b72f..86049e9391bf5ce11ae708034b1b1ad0bd1d03cd 100644 (file)
@@ -80,17 +80,17 @@ class HTMLPurifier_DoctypeRegistry
      */
     public function getDoctypeFromConfig($config) {
         // recommended test
-        $doctype = $config->get('HTML', 'Doctype');
+        $doctype = $config->get('HTML.Doctype');
         if (!empty($doctype)) return $doctype;
-        $doctype = $config->get('HTML', 'CustomDoctype');
+        $doctype = $config->get('HTML.CustomDoctype');
         if (!empty($doctype)) return $doctype;
         // backwards-compatibility
-        if ($config->get('HTML', 'XHTML')) {
+        if ($config->get('HTML.XHTML')) {
             $doctype = 'XHTML 1.0';
         } else {
             $doctype = 'HTML 4.01';
         }
-        if ($config->get('HTML', 'Strict')) {
+        if ($config->get('HTML.Strict')) {
             $doctype .= ' Strict';
         } else {
             $doctype .= ' Transitional';
index b55c7bd79337e337a5e8f28fc1df6befa3f41a8f..aede2c3bb49b25af997901918600751415bc03cd 100644 (file)
@@ -142,7 +142,8 @@ class HTMLPurifier_ElementDef
         $this->_mergeAssocArray($this->excludes, $def->excludes);
 
         if(!empty($def->content_model)) {
-            $this->content_model .= ' | ' . $def->content_model;
+            $this->content_model =
+                str_replace("#SUPER", $this->content_model, $def->content_model);
             $this->child = false;
         }
         if(!empty($def->content_model_type)) {
index 79a42d26ec3cd70b4f5c816ab779a894b881cb10..2b3140caaf575a15c22550b864839c50c0d6b439 100644 (file)
@@ -17,7 +17,7 @@ class HTMLPurifier_Encoder
     /**
      * Error-handler that mutes errors, alternative to shut-up operator.
      */
-    private static function muteErrorHandler() {}
+    public static function muteErrorHandler() {}
 
     /**
      * Cleans a UTF-8 string for well-formedness and SGML validity
@@ -264,12 +264,12 @@ class HTMLPurifier_Encoder
      * Converts a string to UTF-8 based on configuration.
      */
     public static function convertToUTF8($str, $config, $context) {
-        $encoding = $config->get('Core', 'Encoding');
+        $encoding = $config->get('Core.Encoding');
         if ($encoding === 'utf-8') return $str;
         static $iconv = null;
         if ($iconv === null) $iconv = function_exists('iconv');
         set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
-        if ($iconv && !$config->get('Test', 'ForceNoIconv')) {
+        if ($iconv && !$config->get('Test.ForceNoIconv')) {
             $str = iconv($encoding, 'utf-8//IGNORE', $str);
             if ($str === false) {
                 // $encoding is not a valid encoding
@@ -297,15 +297,15 @@ class HTMLPurifier_Encoder
      *       characters being omitted.
      */
     public static function convertFromUTF8($str, $config, $context) {
-        $encoding = $config->get('Core', 'Encoding');
+        $encoding = $config->get('Core.Encoding');
         if ($encoding === 'utf-8') return $str;
         static $iconv = null;
         if ($iconv === null) $iconv = function_exists('iconv');
-        if ($escape = $config->get('Core', 'EscapeNonASCIICharacters')) {
+        if ($escape = $config->get('Core.EscapeNonASCIICharacters')) {
             $str = HTMLPurifier_Encoder::convertToASCIIDumbLossless($str);
         }
         set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
-        if ($iconv && !$config->get('Test', 'ForceNoIconv')) {
+        if ($iconv && !$config->get('Test.ForceNoIconv')) {
             // Undo our previous fix in convertToUTF8, otherwise iconv will barf
             $ascii_fix = HTMLPurifier_Encoder::testEncodingSupportsASCII($encoding);
             if (!$escape && !empty($ascii_fix)) {
index 970f9e0c9d4589da76b07c75252b12e3fa2e772c..bbf78a6630a6b02c8495b1433695336b5e0c9853 100644 (file)
@@ -38,7 +38,7 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter
      * @todo Extend to indicate non-text/css style blocks
      */
     public function preFilter($html, $config, $context) {
-        $tidy = $config->get('FilterParam', 'ExtractStyleBlocksTidyImpl');
+        $tidy = $config->get('Filter.ExtractStyleBlocks.TidyImpl');
         if ($tidy !== null) $this->_tidy = $tidy;
         $html = preg_replace_callback('#<style(?:\s.*)?>(.+)</style>#isU', array($this, 'styleCallback'), $html);
         $style_blocks = $this->_styleMatches;
@@ -62,7 +62,7 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter
      */
     public function cleanCSS($css, $config, $context) {
         // prepare scope
-        $scope = $config->get('FilterParam', 'ExtractStyleBlocksScope');
+        $scope = $config->get('Filter.ExtractStyleBlocks.Scope');
         if ($scope !== null) {
             $scopes = array_map('trim', explode(',', $scope));
         } else {
@@ -120,7 +120,7 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter
         $css = $this->_tidy->print->plain();
         // we are going to escape any special characters <>& to ensure
         // that no funny business occurs (i.e. </style> in a font-family prop).
-        if ($config->get('FilterParam', 'ExtractStyleBlocksEscaping')) {
+        if ($config->get('Filter.ExtractStyleBlocks.Escaping')) {
             $css = str_replace(
                 array('<',    '>',    '&'),
                 array('\3C ', '\3E ', '\26 '),
index a1b96b9e49e59859daa21360e83b5e7f9a273c2c..24bd8a54eddafd0821ba78fad3a77c53bb8a6778 100644 (file)
@@ -42,8 +42,8 @@ class HTMLPurifier_Generator
      */
     public function __construct($config, $context) {
         $this->config = $config;
-        $this->_scriptFix = $config->get('Output', 'CommentScriptContents');
-        $this->_sortAttr = $config->get('Output', 'SortAttr');
+        $this->_scriptFix = $config->get('Output.CommentScriptContents');
+        $this->_sortAttr = $config->get('Output.SortAttr');
         $this->_def = $config->getHTMLDefinition();
         $this->_xhtml = $this->_def->doctype->xml;
     }
@@ -72,7 +72,7 @@ class HTMLPurifier_Generator
         }
 
         // Tidy cleanup
-        if (extension_loaded('tidy') && $this->config->get('Output', 'TidyFormat')) {
+        if (extension_loaded('tidy') && $this->config->get('Output.TidyFormat')) {
             $tidy = new Tidy;
             $tidy->parseString($html, array(
                'indent'=> true,
@@ -86,7 +86,7 @@ class HTMLPurifier_Generator
         }
 
         // Normalize newlines to system defined value
-        $nl = $this->config->get('Output', 'Newline');
+        $nl = $this->config->get('Output.Newline');
         if ($nl === null) $nl = PHP_EOL;
         if ($nl !== "\n") $html = str_replace("\n", $nl, $html);
         return $html;
index 3368821c74fc7ec13ca9e4f43b2c75a5d72fab28..c99ac11eb22aae38c4858342e27838e1d364b20a 100644 (file)
@@ -114,7 +114,7 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
      * @note See HTMLPurifier_HTMLModule::addElement for detailed
      *       parameter and return value descriptions.
      */
-    public function addElement($element_name, $type, $contents, $attr_collections, $attributes) {
+    public function addElement($element_name, $type, $contents, $attr_collections, $attributes = array()) {
         $module = $this->getAnonymousModule();
         // assume that if the user is calling this, the element
         // is safe. This may not be a good idea
@@ -219,7 +219,7 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
      */
     protected function setupConfigStuff($config) {
 
-        $block_wrapper = $config->get('HTML', 'BlockWrapper');
+        $block_wrapper = $config->get('HTML.BlockWrapper');
         if (isset($this->info_content_sets['Block'][$block_wrapper])) {
             $this->info_block_wrapper = $block_wrapper;
         } else {
@@ -227,7 +227,7 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
                 E_USER_ERROR);
         }
 
-        $parent = $config->get('HTML', 'Parent');
+        $parent = $config->get('HTML.Parent');
         $def = $this->manager->getElement($parent, true);
         if ($def) {
             $this->info_parent = $parent;
@@ -244,11 +244,11 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
 
         // setup allowed elements -----------------------------------------
 
-        $allowed_elements = $config->get('HTML', 'AllowedElements');
-        $allowed_attributes = $config->get('HTML', 'AllowedAttributes'); // retrieve early
+        $allowed_elements = $config->get('HTML.AllowedElements');
+        $allowed_attributes = $config->get('HTML.AllowedAttributes'); // retrieve early
 
         if (!is_array($allowed_elements) && !is_array($allowed_attributes)) {
-            $allowed = $config->get('HTML', 'Allowed');
+            $allowed = $config->get('HTML.Allowed');
             if (is_string($allowed)) {
                 list($allowed_elements, $allowed_attributes) = $this->parseTinyMCEAllowedList($allowed);
             }
@@ -334,8 +334,8 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
 
         // setup forbidden elements ---------------------------------------
 
-        $forbidden_elements   = $config->get('HTML', 'ForbiddenElements');
-        $forbidden_attributes = $config->get('HTML', 'ForbiddenAttributes');
+        $forbidden_elements   = $config->get('HTML.ForbiddenElements');
+        $forbidden_attributes = $config->get('HTML.ForbiddenAttributes');
 
         foreach ($this->info as $tag => $info) {
             if (isset($forbidden_elements[$tag])) {
index fdf7b323993dad10d5d0a72b1c8966f59a4ad234..7c15da84fc32938d97f879332eb5dfa17a893dae 100644 (file)
@@ -8,7 +8,7 @@ class HTMLPurifier_HTMLModule_CommonAttributes extends HTMLPurifier_HTMLModule
         'Core' => array(
             0 => array('Style'),
             // 'xml:space' => false,
-            'class' => 'NMTOKENS',
+            'class' => 'Class',
             'id' => 'ID',
             'title' => 'CDATA',
         ),
@@ -20,6 +20,7 @@ class HTMLPurifier_HTMLModule_CommonAttributes extends HTMLPurifier_HTMLModule
             0 => array('Core', 'I18N')
         )
     );
+
 }
 
 // vim: et sw=4 sts=4
index e6ed53aea21bb7eaed7fafef49a5776b4c6bbf73..948d435bcda99e04c30b25ab6402bbb2da8e3716 100644 (file)
@@ -11,7 +11,7 @@ class HTMLPurifier_HTMLModule_Image extends HTMLPurifier_HTMLModule
     public $name = 'Image';
 
     public function setup($config) {
-        $max = $config->get('HTML', 'MaxImgLength');
+        $max = $config->get('HTML.MaxImgLength');
         $img = $this->addElement(
             'img', 'Inline', 'Empty', 'Common',
             array(
@@ -24,7 +24,7 @@ class HTMLPurifier_HTMLModule_Image extends HTMLPurifier_HTMLModule
                 'src*' => new HTMLPurifier_AttrDef_URI(true), // embedded
             )
         );
-        if ($max === null || $config->get('HTML', 'Trusted')) {
+        if ($max === null || $config->get('HTML.Trusted')) {
             $img->attr['height'] =
             $img->attr['width'] = 'Length';
         }
index d908a0ada6c0a53abd7511ed1cc63f25845be7d6..05694b450424e0a63a00e52c21930955b3699776 100644 (file)
@@ -9,7 +9,10 @@ class HTMLPurifier_HTMLModule_Name extends HTMLPurifier_HTMLModule
         $elements = array('a', 'applet', 'form', 'frame', 'iframe', 'img', 'map');
         foreach ($elements as $name) {
             $element = $this->addBlankElement($name);
-            $element->attr['name'] = 'ID';
+            $element->attr['name'] = 'CDATA';
+            if (!$config->get('HTML.Attr.Name.UseCDATA')) {
+                $element->attr_transform_post['NameSync'] = new HTMLPurifier_AttrTransform_NameSync();
+            }
         }
     }
 
index 635e8f2d2b94066863d9446f5224f02cd8fbec9a..8fc03cb1c7eaa924c89ea814f9f7ce719616a2f0 100644 (file)
@@ -10,7 +10,7 @@ class HTMLPurifier_HTMLModule_SafeEmbed extends HTMLPurifier_HTMLModule
 
     public function setup($config) {
 
-        $max = $config->get('HTML', 'MaxImgLength');
+        $max = $config->get('HTML.MaxImgLength');
         $embed = $this->addElement(
             'embed', 'Inline', 'Empty', 'Common',
             array(
index bbda7a2147e0c1e7ed86e9cf664812a1c93f1603..33bac00cf24e2a37f4b543524f1b49d184d5732d 100644 (file)
@@ -16,7 +16,7 @@ class HTMLPurifier_HTMLModule_SafeObject extends HTMLPurifier_HTMLModule
         // These definitions are not intrinsically safe: the attribute transforms
         // are a vital part of ensuring safety.
 
-        $max = $config->get('HTML', 'MaxImgLength');
+        $max = $config->get('HTML.MaxImgLength');
         $object = $this->addElement(
             'object',
             'Inline',
index c9d470648561416bb64b322e51df04c7e12f41a0..21783f18eb82bf9de772ce2d0d8f807cba93944c 100644 (file)
@@ -42,12 +42,12 @@ class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule
         $this->makeFixesForLevel($fixes);
 
         // figure out which fixes to use
-        $level = $config->get('HTML', 'TidyLevel');
+        $level = $config->get('HTML.TidyLevel');
         $fixes_lookup = $this->getFixesForLevel($level);
 
         // get custom fix declarations: these need namespace processing
-        $add_fixes    = $config->get('HTML', 'TidyAdd');
-        $remove_fixes = $config->get('HTML', 'TidyRemove');
+        $add_fixes    = $config->get('HTML.TidyAdd');
+        $remove_fixes = $config->get('HTML.TidyRemove');
 
         foreach ($fixes as $name => $fix) {
             // needs to be refactored a little to implement globbing
index 78f38781d80421567fb9387caa2b662a15ce07de..f5c4a1d2cbb1b23138e197e1aafb749c53698a69 100644 (file)
@@ -199,15 +199,15 @@ class HTMLPurifier_HTMLModuleManager
      */
     public function setup($config) {
 
-        $this->trusted = $config->get('HTML', 'Trusted');
+        $this->trusted = $config->get('HTML.Trusted');
 
         // generate
         $this->doctype = $this->doctypes->make($config);
         $modules = $this->doctype->modules;
 
         // take out the default modules that aren't allowed
-        $lookup = $config->get('HTML', 'AllowedModules');
-        $special_cases = $config->get('HTML', 'CoreModules');
+        $lookup = $config->get('HTML.AllowedModules');
+        $special_cases = $config->get('HTML.CoreModules');
 
         if (is_array($lookup)) {
             foreach ($modules as $k => $m) {
@@ -218,15 +218,15 @@ class HTMLPurifier_HTMLModuleManager
 
         // add proprietary module (this gets special treatment because
         // it is completely removed from doctypes, etc.)
-        if ($config->get('HTML', 'Proprietary')) {
+        if ($config->get('HTML.Proprietary')) {
             $modules[] = 'Proprietary';
         }
 
         // add SafeObject/Safeembed modules
-        if ($config->get('HTML', 'SafeObject')) {
+        if ($config->get('HTML.SafeObject')) {
             $modules[] = 'SafeObject';
         }
-        if ($config->get('HTML', 'SafeEmbed')) {
+        if ($config->get('HTML.SafeEmbed')) {
             $modules[] = 'SafeEmbed';
         }
 
index d546cd751c5b48cd156a6393358a3e9aa47f4559..73215295a510deb0b2b9ab2efd1b68c8e187d093 100644 (file)
@@ -23,7 +23,7 @@ class HTMLPurifier_IDAccumulator
      */
     public static function build($config, $context) {
         $id_accumulator = new HTMLPurifier_IDAccumulator();
-        $id_accumulator->load($config->get('Attr', 'IDBlacklist'));
+        $id_accumulator->load($config->get('Attr.IDBlacklist'));
         return $id_accumulator;
     }
 
index bc093b805c730f2b75beff10b400459ef546eda6..5922f81305e2bc239d3de896c0a84ca672988d6e 100644 (file)
@@ -137,6 +137,12 @@ abstract class HTMLPurifier_Injector
         if (!isset($parent->child->elements[$name]) || isset($parent->excludes[$name])) {
             return false;
         }
+        // check for exclusion
+        for ($i = count($this->currentNesting) - 2; $i >= 0; $i--) {
+            $node = $this->currentNesting[$i];
+            $def  = $this->htmlDefinition->info[$node->name];
+            if (isset($def->excludes[$name])) return false;
+        }
         return true;
     }
 
index 3c706a33aff4934e0d49c54ad6ded042687e2840..ad2455a91ca3a110f96dae9c5a27948d03808807 100644 (file)
@@ -12,7 +12,7 @@ class HTMLPurifier_Injector_PurifierLinkify extends HTMLPurifier_Injector
     public $needed = array('a' => array('href'));
 
     public function prepare($config, $context) {
-        $this->docURL = $config->get('AutoFormatParam', 'PurifierLinkifyDocURL');
+        $this->docURL = $config->get('AutoFormat.PurifierLinkify.DocURL');
         return parent::prepare($config, $context);
     }
 
index d85ca97d92349abb77a6f35719f86169bedd97ba..638bfca03b251b5a30ffcabf297f6addede383b3 100644 (file)
@@ -3,12 +3,14 @@
 class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector
 {
 
-    private $context, $config;
+    private $context, $config, $attrValidator, $removeNbsp, $removeNbspExceptions;
 
     public function prepare($config, $context) {
         parent::prepare($config, $context);
         $this->config = $config;
         $this->context = $context;
+        $this->removeNbsp = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp');
+        $this->removeNbspExceptions = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions');
         $this->attrValidator = new HTMLPurifier_AttrValidator();
     }
 
@@ -17,7 +19,14 @@ class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector
         $next = false;
         for ($i = $this->inputIndex + 1, $c = count($this->inputTokens); $i < $c; $i++) {
             $next = $this->inputTokens[$i];
-            if ($next instanceof HTMLPurifier_Token_Text && $next->is_whitespace) continue;
+            if ($next instanceof HTMLPurifier_Token_Text) {
+                if ($next->is_whitespace) continue;
+                if ($this->removeNbsp && !isset($this->removeNbspExceptions[$token->name])) {
+                    $plain = str_replace("\xC2\xA0", "", $next->data);
+                    $isWsOrNbsp = $plain === '' || ctype_space($plain);
+                    if ($isWsOrNbsp) continue;
+                }
+            }
             break;
         }
         if (!$next || ($next instanceof HTMLPurifier_Token_End && $next->name == $token->name)) {
index baa4422ebfa14c32067ea8df3aaf059863ad6aa7..134ef8c745b49787890d53cb018b13edb8e76f55 100644 (file)
@@ -85,7 +85,7 @@ class HTMLPurifier_LanguageFactory
         // validate language code
         if ($code === false) {
             $code = $this->validator->validate(
-              $config->get('Core', 'Language'), $config, $context
+              $config->get('Core.Language'), $config, $context
             );
         } else {
             $code = $this->validator->validate($code, $config, $context);
index 94588699834d1f6de32508c257a7833f2827b555..8cce008d3dd2312bab7334e8f94a45812f38423c 100644 (file)
@@ -73,12 +73,12 @@ class HTMLPurifier_Lexer
               HTMLPurifier_Lexer::create() is deprecated, please instead
               use %Core.LexerImpl", E_USER_WARNING);
         } else {
-            $lexer = $config->get('Core', 'LexerImpl');
+            $lexer = $config->get('Core.LexerImpl');
         }
 
         $needs_tracking =
-            $config->get('Core', 'MaintainLineNumbers') ||
-            $config->get('Core', 'CollectErrors');
+            $config->get('Core.MaintainLineNumbers') ||
+            $config->get('Core.CollectErrors');
 
         $inst = null;
         if (is_object($lexer)) {
@@ -255,7 +255,7 @@ class HTMLPurifier_Lexer
         $html = str_replace("\r\n", "\n", $html);
         $html = str_replace("\r", "\n", $html);
 
-        if ($config->get('HTML', 'Trusted')) {
+        if ($config->get('HTML.Trusted')) {
             // escape convoluted CDATA
             $html = $this->escapeCommentedCDATA($html);
         }
@@ -264,7 +264,7 @@ class HTMLPurifier_Lexer
         $html = $this->escapeCDATA($html);
 
         // extract body from document if applicable
-        if ($config->get('Core', 'ConvertDocumentToFragment')) {
+        if ($config->get('Core.ConvertDocumentToFragment')) {
             $html = $this->extractBody($html);
         }
 
@@ -285,7 +285,7 @@ class HTMLPurifier_Lexer
      */
     public function extractBody($html) {
         $matches = array();
-        $result = preg_match('!<body[^>]*>(.+?)</body>!is', $html, $matches);
+        $result = preg_match('!<body[^>]*>(.*)</body>!is', $html, $matches);
         if ($result) {
             return $matches[1];
         } else {
index 0db3974bfa0f1324459c5aaa71136035e009b415..20dc2ed48c138402372000214fca3afe463a7655 100644 (file)
@@ -41,7 +41,7 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer
 
         // attempt to armor stray angled brackets that cannot possibly
         // form tags and thus are probably being used as emoticons
-        if ($config->get('Core', 'AggressivelyFixLt')) {
+        if ($config->get('Core.AggressivelyFixLt')) {
             $char = '[^a-z!\/]';
             $comment = "/<!--(.*?)(-->|\z)/is";
             $html = preg_replace_callback($comment, array($this, 'callbackArmorCommentEntities'), $html);
index bfca4533d8c0447f564695f31df8159754bbb063..439409d051b9275affc52fa9e69db283b097ec65 100644 (file)
@@ -33,7 +33,7 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
         // special normalization for script tags without any armor
         // our "armor" heurstic is a < sign any number of whitespaces after
         // the first script tag
-        if ($config->get('HTML', 'Trusted')) {
+        if ($config->get('HTML.Trusted')) {
             $html = preg_replace_callback('#(<script[^>]*>)(\s*[^<].+?)(</script>)#si',
                 array($this, 'scriptCallback'), $html);
         }
@@ -45,12 +45,12 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
         $array = array(); // result array
 
         // This is also treated to mean maintain *column* numbers too
-        $maintain_line_numbers = $config->get('Core', 'MaintainLineNumbers');
+        $maintain_line_numbers = $config->get('Core.MaintainLineNumbers');
 
         if ($maintain_line_numbers === null) {
             // automatically determine line numbering by checking
             // if error collection is on
-            $maintain_line_numbers = $config->get('Core', 'CollectErrors');
+            $maintain_line_numbers = $config->get('Core.CollectErrors');
         }
 
         if ($maintain_line_numbers) {
@@ -67,10 +67,10 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
         $nl = "\n";
         // how often to manually recalculate. This will ALWAYS be right,
         // but it's pretty wasteful. Set to 0 to turn off
-        $synchronize_interval = $config->get('Core', 'DirectLexLineNumberSyncInterval');
+        $synchronize_interval = $config->get('Core.DirectLexLineNumberSyncInterval');
 
         $e = false;
-        if ($config->get('Core', 'CollectErrors')) {
+        if ($config->get('Core.CollectErrors')) {
             $e =& $context->get('ErrorCollector');
         }
 
@@ -345,7 +345,7 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
         if ($string == '') return array(); // no attributes
 
         $e = false;
-        if ($config->get('Core', 'CollectErrors')) {
+        if ($config->get('Core.CollectErrors')) {
             $e =& $context->get('ErrorCollector');
         }
 
index 744dec6597361baa34328773bba6ec2a8516fd1e..02aa656894064763df3173fd1da7aa47d4dff8a7 100644 (file)
@@ -91,7 +91,7 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
         $all = array();
         foreach ($allowed as $key) {
             list($ns, $directive) = $key;
-            $all[$ns][$directive] = $config->get($ns, $directive);
+            $all[$ns][$directive] = $config->get($ns .'.'. $directive);
         }
 
         $ret = '';
@@ -159,7 +159,7 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
             $ret .= $this->end('th');
 
             $ret .= $this->start('td');
-                $def = $this->config->def->info[$ns][$directive];
+                $def = $this->config->def->info["$ns.$directive"];
                 if (is_int($def)) {
                     $allow_null = $def < 0;
                     $type = abs($def);
@@ -248,7 +248,7 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
         $this->prepareGenerator($gen_config);
         // this should probably be split up a little
         $ret = '';
-        $def = $config->def->info[$ns][$directive];
+        $def = $config->def->info["$ns.$directive"];
         if (is_int($def)) {
             $type = abs($def);
         } else {
index 0ec811f8ae2aa114526ecaf06ceae2e2bbfff47e..feb0c32b457097cc85a1276a8b3266eb7acd5ec8 100644 (file)
@@ -42,7 +42,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
 
         // local variables
         $generator = new HTMLPurifier_Generator($config, $context);
-        $escape_invalid_tags = $config->get('Core', 'EscapeInvalidTags');
+        $escape_invalid_tags = $config->get('Core.EscapeInvalidTags');
         $e = $context->get('ErrorCollector', true);
         $t = false; // token index
         $i = false; // injector index
@@ -72,6 +72,8 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
         $custom_injectors = $injectors['Custom'];
         unset($injectors['Custom']); // special case
         foreach ($injectors as $injector => $b) {
+            // XXX: Fix with a legitimate lookup table of enabled filters
+            if (strpos($injector, '.') !== false) continue;
             $injector = "HTMLPurifier_Injector_$injector";
             if (!$b) continue;
             $this->injectors[] = new $injector;
index d30e456db3337a16d136e505c2aeeb67414764b9..cf3a33e406eacd22f71502f93d7a2a4484aba3b2 100644 (file)
@@ -16,14 +16,14 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
         $generator = new HTMLPurifier_Generator($config, $context);
         $result = array();
 
-        $escape_invalid_tags = $config->get('Core', 'EscapeInvalidTags');
-        $remove_invalid_img  = $config->get('Core', 'RemoveInvalidImg');
+        $escape_invalid_tags = $config->get('Core.EscapeInvalidTags');
+        $remove_invalid_img  = $config->get('Core.RemoveInvalidImg');
 
         // currently only used to determine if comments should be kept
-        $trusted = $config->get('HTML', 'Trusted');
+        $trusted = $config->get('HTML.Trusted');
 
-        $remove_script_contents = $config->get('Core', 'RemoveScriptContents');
-        $hidden_elements     = $config->get('Core', 'HiddenElements');
+        $remove_script_contents = $config->get('Core.RemoveScriptContents');
+        $hidden_elements     = $config->get('Core.HiddenElements');
 
         // remove script contents compatibility
         if ($remove_script_contents === true) {
@@ -44,7 +44,7 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
         $context->register('CurrentToken', $token);
 
         $e = false;
-        if ($config->get('Core', 'CollectErrors')) {
+        if ($config->get('Core.CollectErrors')) {
             $e =& $context->get('ErrorCollector');
         }
 
index 183fcfc7e749acfa10d8a89b09a5e82eed2a20a5..ea2b8fe245877781bde3248cd2eadfdda31747d8 100644 (file)
@@ -52,7 +52,7 @@ class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition
 
     protected function setupFilters($config) {
         foreach ($this->registeredFilters as $name => $filter) {
-            $conf = $config->get('URI', $name);
+            $conf = $config->get('URI.' . $name);
             if ($conf !== false && $conf !== null) {
                 $this->addFilter($filter, $config);
             }
@@ -61,15 +61,15 @@ class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition
     }
 
     protected function setupMemberVariables($config) {
-        $this->host = $config->get('URI', 'Host');
-        $base_uri = $config->get('URI', 'Base');
+        $this->host = $config->get('URI.Host');
+        $base_uri = $config->get('URI.Base');
         if (!is_null($base_uri)) {
             $parser = new HTMLPurifier_URIParser();
             $this->base = $parser->parse($base_uri);
             $this->defaultScheme = $this->base->scheme;
             if (is_null($this->host)) $this->host = $this->base->host;
         }
-        if (is_null($this->defaultScheme)) $this->defaultScheme = $config->get('URI', 'DefaultScheme');
+        if (is_null($this->defaultScheme)) $this->defaultScheme = $config->get('URI.DefaultScheme');
     }
 
     public function filter(&$uri, $config, $context) {
index bac56e8b8e4b7a0ac88b35f2c858ef870dd69c2a..045aa0992c662a88ba51cb556e67663467ceae78 100644 (file)
@@ -5,7 +5,7 @@ class HTMLPurifier_URIFilter_HostBlacklist extends HTMLPurifier_URIFilter
     public $name = 'HostBlacklist';
     protected $blacklist = array();
     public function prepare($config) {
-        $this->blacklist = $config->get('URI', 'HostBlacklist');
+        $this->blacklist = $config->get('URI.HostBlacklist');
         return true;
     }
     public function filter(&$uri, $config, $context) {
index 29ed0ed1f27c9575273613e449044342367c59de..efa10a6458ae6e1b171f4a94baeda41488f85a8e 100644 (file)
@@ -9,10 +9,10 @@ class HTMLPurifier_URIFilter_Munge extends HTMLPurifier_URIFilter
     protected $replace = array();
 
     public function prepare($config) {
-        $this->target    = $config->get('URI', $this->name);
+        $this->target    = $config->get('URI.' . $this->name);
         $this->parser    = new HTMLPurifier_URIParser();
-        $this->doEmbed   = $config->get('URI', 'MungeResources');
-        $this->secretKey = $config->get('URI', 'MungeSecretKey');
+        $this->doEmbed   = $config->get('URI.MungeResources');
+        $this->secretKey = $config->get('URI.MungeSecretKey');
         return true;
     }
     public function filter(&$uri, $config, $context) {
@@ -23,6 +23,10 @@ class HTMLPurifier_URIFilter_Munge extends HTMLPurifier_URIFilter
         if (is_null($uri->host) || empty($scheme_obj->browsable)) {
             return true;
         }
+        // don't redirect if target host is our host
+        if ($uri->host === $config->getDefinition('URI')->host) {
+            return true;
+        }
 
         $this->makeReplace($uri, $config, $context);
         $this->replace = array_map('rawurlencode', $this->replace);
index d24732c1829b894e0c43c24e2382974f3ce722f3..576bf7b6d1a44b86e64f78d6169c0764e0f1d0c5 100644 (file)
@@ -36,21 +36,20 @@ class HTMLPurifier_URISchemeRegistry
      */
     public function getScheme($scheme, $config, $context) {
         if (!$config) $config = HTMLPurifier_Config::createDefault();
-        $null = null; // for the sake of passing by reference
 
         // important, otherwise attacker could include arbitrary file
-        $allowed_schemes = $config->get('URI', 'AllowedSchemes');
-        if (!$config->get('URI', 'OverrideAllowedSchemes') &&
+        $allowed_schemes = $config->get('URI.AllowedSchemes');
+        if (!$config->get('URI.OverrideAllowedSchemes') &&
             !isset($allowed_schemes[$scheme])
         ) {
-            return $null;
+            return;
         }
 
         if (isset($this->schemes[$scheme])) return $this->schemes[$scheme];
-        if (!isset($allowed_schemes[$scheme])) return $null;
+        if (!isset($allowed_schemes[$scheme])) return;
 
         $class = 'HTMLPurifier_URIScheme_' . $scheme;
-        if (!class_exists($class)) return $null;
+        if (!class_exists($class)) return;
         $this->schemes[$scheme] = new $class();
         return $this->schemes[$scheme];
     }
index 517f11f1f9e76f0a239a810796d3bc4d4dec8547..cdf31c4d5c0e13990e655a06d9bd345ca01b4bd3 100644 (file)
@@ -1,4 +1,4 @@
-Description of HTML Purifier v3.3.0 library import into Moodle
+Description of HTML Purifier v4.0.0 library import into Moodle
 
 Changes:
  * HMLTModule/Text.php - added  <nolink>, <tex>, <lang> and <algebra> tags
@@ -6,5 +6,3 @@ Changes:
  * AttrDef/Lang.php - relax lang check - needed for multilang
 
 skodak
-
-$Id$
index 8d881dc801a520a9ee40223b30f08858bcd2f676..9a1f730e7b33cd5e3eaa1d9a2909b7fb529b9f55 100644 (file)
@@ -67,7 +67,7 @@
     <location>htmlpurifier</location>
     <name>HTML Purifier</name>
     <license>LGPL</license>
-    <version>4</version>
+    <version>4.0.0</version>
     <licenseversion>2.1+</licenseversion>
   </library>
   <library>