]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-9855 upgrade HTML Purifier to v1.6.1
authorskodak <skodak>
Sun, 20 May 2007 05:35:43 +0000 (05:35 +0000)
committerskodak <skodak>
Sun, 20 May 2007 05:35:43 +0000 (05:35 +0000)
32 files changed:
lib/htmlpurifier/HTMLPurifier.php
lib/htmlpurifier/HTMLPurifier/AttrDef/Enum.php
lib/htmlpurifier/HTMLPurifier/AttrDef/HTML/FrameTarget.php [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/AttrTransform.php
lib/htmlpurifier/HTMLPurifier/AttrTransform/BgColor.php
lib/htmlpurifier/HTMLPurifier/AttrTransform/BoolToCSS.php [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/AttrTransform/Border.php
lib/htmlpurifier/HTMLPurifier/AttrTransform/EnumToCSS.php [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/AttrTransform/ImgSpace.php [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/AttrTransform/Length.php
lib/htmlpurifier/HTMLPurifier/AttrTransform/Name.php
lib/htmlpurifier/HTMLPurifier/CSSDefinition.php
lib/htmlpurifier/HTMLPurifier/ConfigSchema.php
lib/htmlpurifier/HTMLPurifier/ElementDef.php
lib/htmlpurifier/HTMLPurifier/HTMLDefinition.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/Bdo.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/Edit.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/Hypertext.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/Image.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/List.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/Presentation.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/Scripting.php [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/HTMLModule/Tables.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/Target.php [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/HTMLModule/Text.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/TransformToStrict.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/TransformToXHTML11.php
lib/htmlpurifier/HTMLPurifier/HTMLModuleManager.php
lib/htmlpurifier/HTMLPurifier/Lexer/DirectLex.php
lib/htmlpurifier/HTMLPurifier/Strategy/RemoveForeignElements.php
lib/htmlpurifier/HTMLPurifier/TagTransform/Font.php
lib/htmlpurifier/readme_moodle.txt

index 5a0ce99d0b6dc6f7eb85f6fac5dba5157d9a5d3d..3d538bca1a9285c2f07b9f51e18ffd543a491513 100644 (file)
@@ -22,7 +22,7 @@
  */
 
 /*
-    HTML Purifier 1.6.0 - Standards Compliant HTML Filtering
+    HTML Purifier 1.6.1 - Standards Compliant HTML Filtering
     Copyright (C) 2006 Edward Z. Yang
 
     This library is free software; you can redistribute it and/or
@@ -64,7 +64,7 @@ require_once 'HTMLPurifier/Encoder.php';
 class HTMLPurifier
 {
     
-    var $version = '1.6.0';
+    var $version = '1.6.1';
     
     var $config;
     var $filters;
index 3246318f6887a1e9576528ef0aea530d0ea55c33..91a075f87aa7b52965f84e3082a8f27a654957fe 100644 (file)
@@ -5,6 +5,9 @@ require_once 'HTMLPurifier/AttrDef.php';
 // Enum = Enumerated
 /**
  * Validates a keyword against a list of valid values.
+ * @warning The case-insensitive compare of this function uses PHP's
+ *          built-in strtolower and ctype_lower functions, which may
+ *          cause problems with international comparisons
  */
 class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
 {
@@ -34,6 +37,7 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
     function validate($string, $config, &$context) {
         $string = trim($string);
         if (!$this->case_sensitive) {
+            // we may want to do full case-insensitive libraries
             $string = ctype_lower($string) ? $string : strtolower($string);
         }
         $result = isset($this->valid_values[$string]);
diff --git a/lib/htmlpurifier/HTMLPurifier/AttrDef/HTML/FrameTarget.php b/lib/htmlpurifier/HTMLPurifier/AttrDef/HTML/FrameTarget.php
new file mode 100644 (file)
index 0000000..5893bbf
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+HTMLPurifier_ConfigSchema::define(
+    'Attr', 'AllowedFrameTargets', array(), 'lookup',
+    'Lookup table of all allowed link frame targets.  Some commonly used '.
+    'link targets include _blank, _self, _parent and _top. Values should '.
+    'be lowercase, as validation will be done in a case-sensitive manner '.
+    'despite W3C\'s recommendation. XHTML 1.0 Strict does not permit '.
+    'the target attribute so this directive will have no effect in that '.
+    'doctype. XHTML 1.1 does not enable the Target module by default, you '.
+    'will have to manually enable it (see the module documentation for more details.)'
+);
+
+require_once 'HTMLPurifier/AttrDef/Enum.php';
+
+/**
+ * Special-case enum attribute definition that lazy loads allowed frame targets
+ */
+class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
+{
+    
+    var $valid_values = false; // uninitialized value
+    var $case_sensitive = false;
+    
+    function HTMLPurifier_AttrDef_HTML_FrameTarget() {}
+    
+    function validate($string, $config, &$context) {
+        if ($this->valid_values === false) $this->valid_values = $config->get('Attr', 'AllowedFrameTargets');
+        return parent::validate($string, $config, $context);
+    }
+    
+}
+
+?>
\ No newline at end of file
index 3513669ae1eb1d8edea62db7e3bf0390fd2e7431..2fa07b47555a018c111c6f782dda40a2cb0af883 100644 (file)
@@ -29,6 +29,30 @@ class HTMLPurifier_AttrTransform
     function transform($attr, $config, &$context) {
         trigger_error('Cannot call abstract function', E_USER_ERROR);
     }
+    
+    /**
+     * Prepends CSS properties to the style attribute, creating the
+     * attribute if it doesn't exist.
+     * @param $attr Attribute array to process (passed by reference)
+     * @param $css CSS to prepend
+     */
+    function prependCSS(&$attr, $css) {
+        $attr['style'] = isset($attr['style']) ? $attr['style'] : '';
+        $attr['style'] = $css . $attr['style'];
+    }
+    
+    /**
+     * Retrieves and removes an attribute
+     * @param $attr Attribute array to process (passed by reference)
+     * @param $key Key of attribute to confiscate
+     */
+    function confiscateAttr(&$attr, $key) {
+        if (!isset($attr[$key])) return null;
+        $value = $attr[$key];
+        unset($attr[$key]);
+        return $value;
+    }
+    
 }
 
 ?>
\ No newline at end of file
index abfd03427d4bf3c5cc2cdaa09364f3a3c505a878..a7bb2b456458aa6d07806e75b094f074f506ba54 100644 (file)
@@ -12,12 +12,10 @@ extends HTMLPurifier_AttrTransform {
         
         if (!isset($attr['bgcolor'])) return $attr;
         
-        $bgcolor = $attr['bgcolor'];
-        unset($attr['bgcolor']);
+        $bgcolor = $this->confiscateAttr($attr, 'bgcolor');
         // some validation should happen here
         
-        $attr['style'] = isset($attr['style']) ? $attr['style'] : '';
-        $attr['style'] = "background-color:$bgcolor;" . $attr['style'];
+        $this->prependCSS($attr, "background-color:$bgcolor;");
         
         return $attr;
         
diff --git a/lib/htmlpurifier/HTMLPurifier/AttrTransform/BoolToCSS.php b/lib/htmlpurifier/HTMLPurifier/AttrTransform/BoolToCSS.php
new file mode 100644 (file)
index 0000000..f4a16a7
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+
+require_once 'HTMLPurifier/AttrTransform.php';
+
+/**
+ * Pre-transform that changes converts a boolean attribute to fixed CSS
+ */
+class HTMLPurifier_AttrTransform_BoolToCSS
+extends HTMLPurifier_AttrTransform {
+    
+    /**
+     * Name of boolean attribute that is trigger
+     */
+    var $attr;
+    
+    /**
+     * CSS declarations to add to style, needs trailing semicolon
+     */
+    var $css;
+    
+    /**
+     * @param $attr string attribute name to convert from
+     * @param $css string CSS declarations to add to style (needs semicolon)
+     */
+    function HTMLPurifier_AttrTransform_BoolToCSS($attr, $css) {
+        $this->attr = $attr;
+        $this->css  = $css;
+    }
+    
+    function transform($attr, $config, &$context) {
+        if (!isset($attr[$this->attr])) return $attr;
+        unset($attr[$this->attr]);
+        $this->prependCSS($attr, $this->css);
+        return $attr;
+    }
+    
+}
+
+?>
\ No newline at end of file
index 0b745d304563d884e70b82d68648f3e54a0fde8d..10c62e3c5bf04df295cb5a0f6e368c91bd430c9d 100644 (file)
@@ -5,22 +5,14 @@ require_once 'HTMLPurifier/AttrTransform.php';
 /**
  * Pre-transform that changes deprecated border attribute to CSS.
  */
-class HTMLPurifier_AttrTransform_Border
-extends HTMLPurifier_AttrTransform {
+class HTMLPurifier_AttrTransform_Border extends HTMLPurifier_AttrTransform {
 
     function transform($attr, $config, &$context) {
-        
         if (!isset($attr['border'])) return $attr;
-        
-        $border_width = $attr['border'];
-        unset($attr['border']);
+        $border_width = $this->confiscateAttr($attr, 'border');
         // some validation should happen here
-        
-        $attr['style'] = isset($attr['style']) ? $attr['style'] : '';
-        $attr['style'] = "border:{$border_width}px solid;" . $attr['style'];
-        
+        $this->prependCSS($attr, "border:{$border_width}px solid;");
         return $attr;
-        
     }
     
 }
diff --git a/lib/htmlpurifier/HTMLPurifier/AttrTransform/EnumToCSS.php b/lib/htmlpurifier/HTMLPurifier/AttrTransform/EnumToCSS.php
new file mode 100644 (file)
index 0000000..ed4dfc3
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+
+require_once 'HTMLPurifier/AttrTransform.php';
+
+/**
+ * Generic pre-transform that converts an attribute with a fixed number of
+ * values (enumerated) to CSS.
+ */
+class HTMLPurifier_AttrTransform_EnumToCSS extends HTMLPurifier_AttrTransform {
+    
+    /**
+     * Name of attribute to transform from
+     */
+    var $attr;
+    
+    /**
+     * Lookup array of attribute values to CSS
+     */
+    var $enumToCSS = array();
+    
+    /**
+     * Case sensitivity of the matching
+     * @warning Currently can only be guaranteed to work with ASCII
+     *          values.
+     */
+    var $caseSensitive = false;
+    
+    /**
+     * @param $attr String attribute name to transform from
+     * @param $enumToCSS Lookup array of attribute values to CSS
+     * @param $case_sensitive Boolean case sensitivity indicator, default false
+     */
+    function HTMLPurifier_AttrTransform_EnumToCSS($attr, $enum_to_css, $case_sensitive = false) {
+        $this->attr = $attr;
+        $this->enumToCSS = $enum_to_css;
+        $this->caseSensitive = (bool) $case_sensitive;
+    }
+    
+    function transform($attr, $config, &$context) {
+        
+        if (!isset($attr[$this->attr])) return $attr;
+        
+        $value = trim($attr[$this->attr]);
+        unset($attr[$this->attr]);
+        
+        if (!$this->caseSensitive) $value = strtolower($value);
+        
+        if (!isset($this->enumToCSS[$value])) {
+            return $attr;
+        }
+        
+        $this->prependCSS($attr, $this->enumToCSS[$value]);
+        
+        return $attr;
+        
+    }
+    
+}
+
+?>
\ No newline at end of file
diff --git a/lib/htmlpurifier/HTMLPurifier/AttrTransform/ImgSpace.php b/lib/htmlpurifier/HTMLPurifier/AttrTransform/ImgSpace.php
new file mode 100644 (file)
index 0000000..53c787e
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+
+require_once 'HTMLPurifier/AttrTransform.php';
+
+/**
+ * Pre-transform that changes deprecated hspace and vspace attributes to CSS
+ */
+class HTMLPurifier_AttrTransform_ImgSpace
+extends HTMLPurifier_AttrTransform {
+    
+    var $attr;
+    var $css = array(
+        'hspace' => array('left', 'right'),
+        'vspace' => array('top', 'bottom')
+    );
+    
+    function HTMLPurifier_AttrTransform_ImgSpace($attr) {
+        $this->attr = $attr;
+        if (!isset($this->css[$attr])) {
+            trigger_error(htmlspecialchars($attr) . ' is not valid space attribute');
+        }
+    }
+    
+    function transform($attr, $config, &$context) {
+        
+        if (!isset($attr[$this->attr])) return $attr;
+        
+        $width = $this->confiscateAttr($attr, $this->attr);
+        // some validation could happen here
+        
+        if (!isset($this->css[$this->attr])) return $attr;
+        
+        $style = '';
+        foreach ($this->css[$this->attr] as $suffix) {
+            $property = "margin-$suffix";
+            $style .= "$property:{$width}px;";
+        }
+        
+        $this->prependCSS($attr, $style);
+        
+        return $attr;
+        
+    }
+    
+}
+
+?>
\ No newline at end of file
index 16d3d1d8caaf0e1e4ebad3a627acf85d7b100173..2292aa133e9ee25ea618f4b1eed7ebadb2613fcd 100644 (file)
@@ -18,13 +18,9 @@ class HTMLPurifier_AttrTransform_Length extends HTMLPurifier_AttrTransform
     
     function transform($attr, $config, &$context) {
         if (!isset($attr[$this->name])) return $attr;
-        $length = $attr[$this->name];
-        unset($attr[$this->name]);
+        $length = $this->confiscateAttr($attr, $this->name);
         if(ctype_digit($length)) $length .= 'px';
-        
-        $attr['style'] = isset($attr['style']) ? $attr['style'] : '';
-        $attr['style'] = $this->cssName . ":$length;" . $attr['style'];
-        
+        $this->prependCSS($attr, $this->cssName . ":$length;");
         return $attr;
     }
     
index 0f815b69e3904f76fa42e7e390c5e1458c57004f..f14c147989c2dec5a50ed519a796eb086d680e07 100644 (file)
@@ -9,21 +9,11 @@ class HTMLPurifier_AttrTransform_Name extends HTMLPurifier_AttrTransform
 {
     
     function transform($attr, $config, &$context) {
-        
         if (!isset($attr['name'])) return $attr;
-        
-        $name = $attr['name'];
-        unset($attr['name']);
-        
-        if (isset($attr['id'])) {
-            // ID already set, discard name
-            return $attr;
-        }
-        
-        $attr['id'] = $name;
-        
+        $id = $this->confiscateAttr($attr, 'name');
+        if ( isset($attr['id']))   return $attr;
+        $attr['id'] = $id;
         return $attr;
-        
     }
     
 }
index 5de49b69b3e0b22b84f66f10c995426cfbaebafd..23a66ab76af98392f855ac6b57fc24ba40b77dd9 100644 (file)
@@ -206,6 +206,9 @@ class HTMLPurifier_CSSDefinition
             new HTMLPurifier_AttrDef_CSS_Percentage()
         ));
         
+        // partial support
+        $this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(array('nowrap'));
+        
     }
     
 }
index 9f1f3e3eb30984bf5a1c1454a89b264f4ddbc698..940e8e61992e66b3df4677b8413e8f559940e88f 100644 (file)
@@ -334,6 +334,10 @@ class HTMLPurifier_ConfigSchema {
             case 'hash':
             case 'lookup':
                 if (is_string($var)) {
+                    // special case: technically, this is an array with
+                    // a single empty string item, but having an empty
+                    // array is more intuitive
+                    if ($var == '') return array();
                     // simplistic string to array method that only works
                     // for simple lists of tag names or alphanumeric characters
                     $var = explode(',',$var);
index 21bc5f36a328634df56e7c349ae1909face1dc1e..73c94abe1382d960dd2f8f1cdf57ecb2912c5f81 100644 (file)
@@ -95,7 +95,7 @@ class HTMLPurifier_ElementDef
         
         // later keys takes precedence
         foreach($def->attr as $k => $v) {
-            if ($k == 0) {
+            if ($k === 0) {
                 // merge in the includes
                 // sorry, no way to override an include
                 foreach ($v as $v2) {
index 3af445ceb0bbb634d48e1070f9e022392beffaf3..c1dd6535c48c5f263a005ca7e207ea66b8860fcd 100644 (file)
@@ -183,9 +183,18 @@ class HTMLPurifier_HTMLDefinition
         $this->manager->setup($this->config);
         
         foreach ($this->manager->activeModules as $module) {
-            foreach($module->info_tag_transform         as $k => $v) $this->info_tag_transform[$k]      = $v;
-            foreach($module->info_attr_transform_pre    as $k => $v) $this->info_attr_transform_pre[$k] = $v;
-            foreach($module->info_attr_transform_post   as $k => $v) $this->info_attr_transform_post[$k]= $v;
+            foreach($module->info_tag_transform         as $k => $v) {
+                if ($v === false) unset($this->info_tag_transform[$k]);
+                else $this->info_tag_transform[$k] = $v;
+            }
+            foreach($module->info_attr_transform_pre    as $k => $v) {
+                if ($v === false) unset($this->info_attr_transform_pre[$k]);
+                else $this->info_attr_transform_pre[$k] = $v;
+            }
+            foreach($module->info_attr_transform_post   as $k => $v) {
+                if ($v === false) unset($this->info_attr_transform_post[$k]);
+                else $this->info_attr_transform_post[$k] = $v;
+            }
         }
         
         $this->info = $this->manager->getElements($this->config);
index 17e5e987fde9239eb16bbfb96b36db39bb1dfbce..6feae0050dc8f76342e8941425d021145b0857c9 100644 (file)
@@ -12,7 +12,6 @@ class HTMLPurifier_HTMLModule_Bdo extends HTMLPurifier_HTMLModule
     
     var $name = 'Bdo';
     var $elements = array('bdo');
-    var $info = array();
     var $content_sets = array('Inline' => 'bdo');
     var $attr_collections = array(
         'I18N' => array('dir' => false)
index 6a415906e6392fb51cd4ed49a584ce6f037bcf1f..c3dc019700022ff45803a8e25d1306a4d7cc60ff 100644 (file)
@@ -12,7 +12,6 @@ class HTMLPurifier_HTMLModule_Edit extends HTMLPurifier_HTMLModule
     
     var $name = 'Edit';
     var $elements = array('del', 'ins');
-    var $info = array();
     var $content_sets = array('Inline' => 'del | ins');
     
     function HTMLPurifier_HTMLModule_Edit() {
index e285e8ba1f0ba13e97d52d7f857b5eb9edb9b579..baa20fd14b22641ad9cac5d1aadc3011fcec5362 100644 (file)
@@ -11,7 +11,6 @@ class HTMLPurifier_HTMLModule_Hypertext extends HTMLPurifier_HTMLModule
     
     var $name = 'Hypertext';
     var $elements = array('a');
-    var $info = array();
     var $content_sets = array('Inline' => 'a');
     
     function HTMLPurifier_HTMLModule_Hypertext() {
index 3852836de7cae5618d6af9cc3f01789fc19a7b52..bf234b13727b5a618d0adfcee3fd2a8747cd7175 100644 (file)
@@ -15,7 +15,6 @@ class HTMLPurifier_HTMLModule_Image extends HTMLPurifier_HTMLModule
     
     var $name = 'Image';
     var $elements = array('img');
-    var $info = array();
     var $content_sets = array('Inline' => 'img');
     
     function HTMLPurifier_HTMLModule_Image() {
index c74982df4e43d86371854fe6b6d603a5827a9737..f9f2c4e21f572d22b05f1a4ba69189e126880ec6 100644 (file)
@@ -10,7 +10,7 @@ class HTMLPurifier_HTMLModule_List extends HTMLPurifier_HTMLModule
     
     var $name = 'List';
     var $elements = array('dl', 'dt', 'dd', 'ol', 'ul', 'li');
-    var $info = array();
+    
     // According to the abstract schema, the List content set is a fully formed
     // one or more expr, but it invariably occurs in an optional declaration
     // so we're not going to do that subtlety. It might cause trouble
index 42d9c11e4680464ca1302ca77886a5f1e5a76f15..5c80db407b1a068ae2848d46130347c700845598 100644 (file)
@@ -17,7 +17,6 @@ class HTMLPurifier_HTMLModule_Presentation extends HTMLPurifier_HTMLModule
     
     var $name = 'Presentation';
     var $elements = array('b', 'big', 'hr', 'i', 'small', 'sub', 'sup', 'tt');
-    var $info = array();
     var $content_sets = array(
         'Block' => 'hr',
         'Inline' => 'b | big | i | small | sub | sup | tt'
diff --git a/lib/htmlpurifier/HTMLPurifier/HTMLModule/Scripting.php b/lib/htmlpurifier/HTMLPurifier/HTMLModule/Scripting.php
new file mode 100644 (file)
index 0000000..e3ef802
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+
+/*
+
+WARNING: THIS MODULE IS EXTREMELY DANGEROUS AS IT ENABLES INLINE SCRIPTING
+INSIDE HTML PURIFIER DOCUMENTS. USE ONLY WITH TRUSTED USER INPUT!!!
+
+Usage:
+
+require_once 'HTMLPurifier/HTMLModule/Scripting.php';
+$def =& $config->getHTMLDefinition(true); // get the raw version
+$def->manager->addModule('Scripting');
+
+This must come before any other calls to getHTMLDefinition()
+
+*/
+
+/**
+ * Implements required attribute stipulation for <script>
+ */
+class HTMLPurifier_AttrTransform_ScriptRequired extends HTMLPurifier_AttrTransform
+{
+    function transform($attr, $config, &$context) {
+        if (!isset($attr['type'])) {
+            $attr['type'] = 'text/javascript';
+        }
+        return $attr;
+    }
+}
+
+/**
+ * XHTML 1.1 Scripting module, defines elements that are used to contain
+ * information pertaining to executable scripts or the lack of support
+ * for executable scripts.
+ * @note This module does not contain inline scripting elements
+ */
+class HTMLPurifier_HTMLModule_Scripting extends HTMLPurifier_HTMLModule
+{
+    var $name = 'Scripting';
+    var $elements = array('script', 'noscript');
+    var $content_sets = array('Block' => 'script | noscript', 'Inline' => 'script | noscript');
+    
+    function HTMLPurifier_HTMLModule_Scripting() {
+        // TODO: create custom child-definition for noscript that
+        // auto-wraps stray #PCDATA in a similar manner to 
+        // blockquote's custom definition (we would use it but
+        // blockquote's contents are optional while noscript's contents
+        // are required)
+        foreach ($this->elements as $element) {
+            $this->info[$element] = new HTMLPurifier_ElementDef();
+        }
+        $this->info['noscript']->attr = array( 0 => array('Common') );
+        $this->info['noscript']->content_model = 'Heading | List | Block';
+        $this->info['noscript']->content_model_type = 'required';
+        $this->info['script']->attr = array(
+            'defer' => new HTMLPurifier_AttrDef_Enum(array('defer')),
+            'src'   => new HTMLPurifier_AttrDef_URI(true),
+            'type'  => new HTMLPurifier_AttrDef_Enum(array('text/javascript'))
+        );
+        $this->info['script']->content_model = '#PCDATA';
+        $this->info['script']->content_model_type = 'optional';
+        $this->info['script']->attr_transform_post['type'] =
+            new HTMLPurifier_AttrTransform_ScriptRequired();
+    }
+}
+
+?>
\ No newline at end of file
index ea41f5b103cc2fa81e5e9ec8b49e94bb5356cb37..003ff62487d82e6ee35c2105196ee3fd9cfdaa88 100644 (file)
@@ -12,7 +12,6 @@ class HTMLPurifier_HTMLModule_Tables extends HTMLPurifier_HTMLModule
     var $name = 'Tables';
     var $elements = array('caption', 'table', 'td', 'th', 'tr', 'col',
         'colgroup', 'tbody', 'thead', 'tfoot');
-    var $info = array();
     var $content_sets = array('Block' => 'table');
     
     function HTMLPurifier_HTMLModule_Tables() {
diff --git a/lib/htmlpurifier/HTMLPurifier/HTMLModule/Target.php b/lib/htmlpurifier/HTMLPurifier/HTMLModule/Target.php
new file mode 100644 (file)
index 0000000..1c2104b
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+
+require_once 'HTMLPurifier/AttrDef/HTML/FrameTarget.php';
+
+/**
+ * XHTML 1.1 Target Module, defines target attribute in link elements.
+ */
+class HTMLPurifier_HTMLModule_Target extends HTMLPurifier_HTMLModule
+{
+    
+    var $name = 'Target';
+    var $elements = array('a');
+    
+    function HTMLPurifier_HTMLModule_Target() {
+        foreach ($this->elements as $e) {
+            $this->info[$e] = new HTMLPurifier_ElementDef();
+            $this->info[$e]->standalone = false;
+            $this->info[$e]->attr = array(
+                'target' => new HTMLPurifier_AttrDef_HTML_FrameTarget()
+            );
+        }
+    }
+    
+}
+
+?>
\ No newline at end of file
index bac05986c67f24c05425c9779a1d3dcfaa08fda6..6f81dcf389b9f2b6ea16be7d1aac88f57519ad6e 100644 (file)
@@ -22,8 +22,6 @@ class HTMLPurifier_HTMLModule_Text extends HTMLPurifier_HTMLModule
         'h4', 'h5', 'h6', 'kbd', 'p', 'pre', 'q', 'samp', 'span', 'strong',
         'var', 'nolink', 'tex', 'algebra'); //moodle modification
     
-    var $info = array();
-    
     var $content_sets = array(
         'Heading' => 'h1 | h2 | h3 | h4 | h5 | h6',
         'Block' => 'address | blockquote | div | p | pre | nolink | tex | algebra', //moodle modification
index cdbe3733f2d1a54c15208207dffd3700727be367..0b6c8370abcc87a62c8ca92963f9764b472ac9a5 100644 (file)
@@ -7,11 +7,13 @@ require_once 'HTMLPurifier/TagTransform/Center.php';
 require_once 'HTMLPurifier/TagTransform/Font.php';
 
 require_once 'HTMLPurifier/AttrTransform/Lang.php';
-require_once 'HTMLPurifier/AttrTransform/TextAlign.php';
 require_once 'HTMLPurifier/AttrTransform/BgColor.php';
+require_once 'HTMLPurifier/AttrTransform/BoolToCSS.php';
 require_once 'HTMLPurifier/AttrTransform/Border.php';
 require_once 'HTMLPurifier/AttrTransform/Name.php';
 require_once 'HTMLPurifier/AttrTransform/Length.php';
+require_once 'HTMLPurifier/AttrTransform/ImgSpace.php';
+require_once 'HTMLPurifier/AttrTransform/EnumToCSS.php';
 
 /**
  * Proprietary module that transforms deprecated elements into Strict
@@ -25,7 +27,8 @@ class HTMLPurifier_HTMLModule_TransformToStrict extends HTMLPurifier_HTMLModule
     
     // we're actually modifying these elements, not defining them
     var $elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p',
-        'blockquote', 'table', 'td', 'th', 'tr', 'img', 'a', 'hr');
+        'blockquote', 'table', 'td', 'th', 'tr', 'img', 'a', 'hr', 'br',
+        'caption', 'ul', 'ol', 'li');
     
     var $info_tag_transform = array(
         // placeholders, see constructor for definitions
@@ -47,6 +50,13 @@ class HTMLPurifier_HTMLModule_TransformToStrict extends HTMLPurifier_HTMLModule
     
     function HTMLPurifier_HTMLModule_TransformToStrict() {
         
+        // behavior with transformations when there's another CSS property
+        // working on it is interesting: the CSS will *always* override
+        // the deprecated attribute, whereas an inline CSS declaration will
+        // override the corresponding declaration in, say, an external
+        // stylesheet. This behavior won't affect most people, but it
+        // does represent an operational difference we CANNOT fix.
+        
         // deprecated tag transforms
         $this->info_tag_transform['font']   = new HTMLPurifier_TagTransform_Font();
         $this->info_tag_transform['menu']   = new HTMLPurifier_TagTransform_Simple('ul');
@@ -59,6 +69,11 @@ class HTMLPurifier_HTMLModule_TransformToStrict extends HTMLPurifier_HTMLModule
         }
         
         // deprecated attribute transforms
+        
+        // align battery
+        $align_lookup = array();
+        $align_values = array('left', 'right', 'center', 'justify');
+        foreach ($align_values as $v) $align_lookup[$v] = "text-align:$v;";
         $this->info['h1']->attr_transform_pre['align'] =
         $this->info['h2']->attr_transform_pre['align'] =
         $this->info['h3']->attr_transform_pre['align'] =
@@ -66,7 +81,7 @@ class HTMLPurifier_HTMLModule_TransformToStrict extends HTMLPurifier_HTMLModule
         $this->info['h5']->attr_transform_pre['align'] =
         $this->info['h6']->attr_transform_pre['align'] =
         $this->info['p'] ->attr_transform_pre['align'] = 
-                    new HTMLPurifier_AttrTransform_TextAlign();
+                    new HTMLPurifier_AttrTransform_EnumToCSS('align', $align_lookup);
         
         // xml:lang <=> lang mirroring, implement in TransformToStrict,
         // this is overridden in TransformToXHTML11
@@ -92,9 +107,86 @@ class HTMLPurifier_HTMLModule_TransformToStrict extends HTMLPurifier_HTMLModule
         $this->info['th']->attr_transform_pre['width'] = 
         $this->info['hr']->attr_transform_pre['width'] = new HTMLPurifier_AttrTransform_Length('width');
         
+        $this->info['td']->attr_transform_pre['nowrap'] = 
+        $this->info['th']->attr_transform_pre['nowrap'] = new HTMLPurifier_AttrTransform_BoolToCSS('nowrap', 'white-space:nowrap;');
+        
         $this->info['td']->attr_transform_pre['height'] = 
         $this->info['th']->attr_transform_pre['height'] = new HTMLPurifier_AttrTransform_Length('height');
         
+        $this->info['img']->attr_transform_pre['hspace'] = new HTMLPurifier_AttrTransform_ImgSpace('hspace');
+        $this->info['img']->attr_transform_pre['vspace'] = new HTMLPurifier_AttrTransform_ImgSpace('vspace');
+        
+        $this->info['hr']->attr_transform_pre['size'] = new HTMLPurifier_AttrTransform_Length('size', 'height');
+        
+        // this transformation is not precise but often good enough.
+        // different browsers use different styles to designate noshade
+        $this->info['hr']->attr_transform_pre['noshade'] = new HTMLPurifier_AttrTransform_BoolToCSS('noshade', 'color:#808080;background-color:#808080;border: 0;');
+        
+        $this->info['br']->attr_transform_pre['clear'] =
+            new HTMLPurifier_AttrTransform_EnumToCSS('clear', array(
+                'left' => 'clear:left;',
+                'right' => 'clear:right;',
+                'all' => 'clear:both;',
+                'none' => 'clear:none;',
+            ));
+        
+        // this is a slightly unreasonable attribute
+        $this->info['caption']->attr_transform_pre['align'] =
+            new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
+                // we're following IE's behavior, not Firefox's, due
+                // to the fact that no one supports caption-side:right,
+                // W3C included (with CSS 2.1)
+                'left' => 'text-align:left;',
+                'right' => 'text-align:right;',
+                'top' => 'caption-side:top;',
+                'bottom' => 'caption-side:bottom;' // not supported by IE
+            ));
+        
+        $this->info['table']->attr_transform_pre['align'] = 
+            new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
+                'left' => 'float:left;',
+                'center' => 'margin-left:auto;margin-right:auto;',
+                'right' => 'float:right;'
+            ));
+        
+        $this->info['img']->attr_transform_pre['align'] = 
+            new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
+                'left' => 'float:left;',
+                'right' => 'float:right;',
+                'top' => 'vertical-align:top;',
+                'middle' => 'vertical-align:middle;',
+                'bottom' => 'vertical-align:baseline;',
+            ));
+        
+        $this->info['hr']->attr_transform_pre['align'] = 
+            new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
+                'left' => 'margin-left:0;margin-right:auto;text-align:left;',
+                'center' => 'margin-left:auto;margin-right:auto;text-align:center;',
+                'right' => 'margin-left:auto;margin-right:0;text-align:right;'
+            ));
+        
+        $ul_types = array(
+            'disc'   => 'list-style-type:disc;',
+            'square' => 'list-style-type:square;',
+            'circle' => 'list-style-type:circle;'
+        );
+        $ol_types = array(
+            '1'   => 'list-style-type:decimal;',
+            'i'   => 'list-style-type:lower-roman;',
+            'I'   => 'list-style-type:upper-roman;',
+            'a'   => 'list-style-type:lower-alpha;',
+            'A'   => 'list-style-type:upper-alpha;'
+        );
+        $li_types = $ul_types + $ol_types;
+        
+        $this->info['ul']->attr_transform_pre['type'] =
+            new HTMLPurifier_AttrTransform_EnumToCSS('type', $ul_types);
+        $this->info['ol']->attr_transform_pre['type'] =
+            new HTMLPurifier_AttrTransform_EnumToCSS('type', $ol_types, true);
+        $this->info['li']->attr_transform_pre['type'] =
+            new HTMLPurifier_AttrTransform_EnumToCSS('type', $li_types, true);
+        
+        
     }
     
     var $defines_child_def = true;
index 0915f5b6e5e05dfa2efdd3122192a770569195d2..68aac61312eaf178d7805e2d1eacac593e6fb1df 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+require_once 'HTMLPurifier/AttrTransform/Lang.php';
+
 /**
  * Proprietary module that transforms XHTML 1.0 deprecated aspects into
  * XHTML 1.1 compliant ones, when possible. For maximum effectiveness,
@@ -25,6 +27,10 @@ class HTMLPurifier_HTMLModule_TransformToXHTML11 extends HTMLPurifier_HTMLModule
         'lang' => false // remove it
     );
     
+    function HTMLPurifier_HTMLModule_TransformToXHTML11() {
+        $this->info_attr_transform_pre['lang'] = new HTMLPurifier_AttrTransform_Lang();
+    }
+    
 }
 
 ?>
\ No newline at end of file
index e0090472ca0242c634cbd518931e6451a0285d09..81ef13a5f4263184f4fb725f35de9523d3a290f7 100644 (file)
@@ -22,6 +22,7 @@ require_once 'HTMLPurifier/HTMLModule/Tables.php';
 require_once 'HTMLPurifier/HTMLModule/Image.php';
 require_once 'HTMLPurifier/HTMLModule/StyleAttribute.php';
 require_once 'HTMLPurifier/HTMLModule/Legacy.php';
+require_once 'HTMLPurifier/HTMLModule/Target.php';
 
 // proprietary modules
 require_once 'HTMLPurifier/HTMLModule/TransformToStrict.php';
@@ -134,6 +135,7 @@ class HTMLPurifier_HTMLModuleManager
             'CommonAttributes',
             'Text', 'Hypertext', 'List', 'Presentation',
             'Edit', 'Bdo', 'Tables', 'Image', 'StyleAttribute',
+            'Target',
             // define-redefine
             'Legacy',
             // redefine
@@ -155,7 +157,7 @@ class HTMLPurifier_HTMLModuleManager
             'HTML 4.01 Transitional' => array(array('XHTML 1.0 Transitional')),
             'HTML 4.01 Strict' => array(array('XHTML 1.0 Strict')),
             // XHTML definitions
-            'XHTML 1.0 Transitional' => array( array('XHTML 1.0 Strict'), 'Legacy' ),
+            'XHTML 1.0 Transitional' => array( array('XHTML 1.0 Strict'), 'Legacy', 'Target' ),
             'XHTML 1.0 Strict' => array(array('_Common')),
             'XHTML 1.1' => array(array('_Common')),
         );
@@ -206,20 +208,35 @@ class HTMLPurifier_HTMLModuleManager
      * @param $module Mixed: string module name, with or without
      *                HTMLPurifier_HTMLModule prefix, or instance of
      *                subclass of HTMLPurifier_HTMLModule.
+     * @note This function will not call autoload, you must instantiate
+     *       (and thus invoke) autoload outside the method.
+     * @note If a string is passed as a module name, different variants
+     *       will be tested in this order:
+     *          - Check for HTMLPurifier_HTMLModule_$name
+     *          - Check all prefixes with $name in order they were added
+     *          - Check for literal object name
+     *          - Throw fatal error
+     *       If your object name collides with an internal class, specify
+     *       your module manually.
      */
     function addModule($module) {
         if (is_string($module)) {
             $original_module = $module;
-            if (!class_exists($module)) {
-                foreach ($this->prefixes as $prefix) {
-                    $module = $prefix . $original_module;
-                    if (class_exists($module)) break;
+            $ok = false;
+            foreach ($this->prefixes as $prefix) {
+                $module = $prefix . $original_module;
+                if ($this->_classExists($module)) {
+                    $ok = true;
+                    break;
                 }
             }
-            if (!class_exists($module)) {
-                trigger_error($original_module . ' module does not exist',
-                    E_USER_ERROR);
-                return;
+            if (!$ok) {
+                $module = $original_module;
+                if (!$this->_classExists($module)) {
+                    trigger_error($original_module . ' module does not exist',
+                        E_USER_ERROR);
+                    return;
+                }
             }
             $module = new $module();
         }
@@ -230,6 +247,23 @@ class HTMLPurifier_HTMLModuleManager
         }
     }
     
+    /**
+     * Safely tests for class existence without invoking __autoload in PHP5
+     * @param $name String class name to test
+     * @private
+     */
+    function _classExists($name) {
+        static $is_php_4 = null;
+        if ($is_php_4 === null) {
+            $is_php_4 = version_compare(PHP_VERSION, '5', '<');
+        }
+        if ($is_php_4) {
+            return class_exists($name);
+        } else {
+            return class_exists($name, false);
+        }
+    }
+    
     /**
      * Makes a collection active, while also making it valid if not
      * already done so. See $activeModules for the semantics of "active".
@@ -491,7 +525,8 @@ class HTMLPurifier_HTMLModuleManager
         
         $elements = array();
         foreach ($this->activeModules as $module) {
-            foreach ($module->elements as $name) {
+            foreach ($module->info as $name => $v) {
+                if (isset($elements[$name])) continue;
                 $elements[$name] = $this->getElement($name, $config);
             }
         }
@@ -555,4 +590,4 @@ class HTMLPurifier_HTMLModuleManager
     
 }
 
-?>
\ No newline at end of file
+?>
index 65d95a7cf910f6f5e18a3bd54f6f8fed71418aec..57d116a4fb36ba22cde4731a48950dd904911695 100644 (file)
@@ -110,6 +110,23 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
                     continue;
                 }
                 
+                // Check leading character is alnum, if not, we may
+                // have accidently grabbed an emoticon. Translate into
+                // text and go our merry way
+                if (!ctype_alnum($segment[0])) {
+                    $array[] = new
+                        HTMLPurifier_Token_Text(
+                            '<' .
+                            $this->parseData(
+                                $segment
+                            ) . 
+                            '>'
+                        );
+                    $cursor = $position_next_gt + 1;
+                    $inside_tag = false;
+                    continue;
+                }
+                
                 // Check if it is explicitly self closing, if so, remove
                 // trailing slash. Remember, we could have a tag like <br>, so
                 // any later token processing scripts must convert improperly
index 27caf3645fd1d72fcd2d62f2197619c0be406ed1..cb5c4dd1b3b72c7447b164f21f41fdf6a9b0ec93 100644 (file)
@@ -29,6 +29,7 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
         $generator = new HTMLPurifier_Generator();
         $result = array();
         $escape_invalid_tags = $config->get('Core', 'EscapeInvalidTags');
+        $remove_invalid_img  = $config->get('Core', 'RemoveInvalidImg');
         foreach($tokens as $token) {
             if (!empty( $token->is_tag )) {
                 // DEFINITION CALL
@@ -37,7 +38,7 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
                     
                     // hard-coded image special case, pre-emptively drop
                     // if not available. Probably not abstract-able
-                    if ( $token->name == 'img' ) {
+                    if ( $token->name == 'img' && $remove_invalid_img ) {
                         if (!isset($token->attr['src'])) {
                             continue;
                         }
index ae6d78380962c7a7bc9e3824f6fbde686e70cd2c..dedaf8b245a069c584c5c4d1b31a0259d8bc1731 100644 (file)
@@ -20,6 +20,7 @@ class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform
     var $transform_to = 'span';
     
     var $_size_lookup = array(
+        '0' => 'xx-small',
         '1' => 'xx-small',
         '2' => 'small',
         '3' => 'medium',
@@ -28,9 +29,10 @@ class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform
         '6' => 'xx-large',
         '7' => '300%',
         '-1' => 'smaller',
-        '+1' => 'larger',
         '-2' => '60%',
+        '+1' => 'larger',
         '+2' => '150%',
+        '+3' => '200%',
         '+4' => '300%'
     );
     
@@ -58,6 +60,15 @@ class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform
         
         // handle size transform
         if (isset($attr['size'])) {
+            // normalize large numbers
+            if ($attr['size']{0} == '+' || $attr['size']{0} == '-') {
+                $size = (int) $attr['size'];
+                if ($size < -2) $attr['size'] = '-2';
+                if ($size > 4)  $attr['size'] = '+4';
+            } else {
+                $size = (int) $attr['size'];
+                if ($size > 7) $attr['size'] = '7';
+            }
             if (isset($this->_size_lookup[$attr['size']])) {
                 $prepend_style .= 'font-size:' .
                   $this->_size_lookup[$attr['size']] . ';';
index 53cf1070b15b09a0a97d9dc79abd220773bffb44..34af69a1c1616747eeb63625052322813e45b862 100644 (file)
@@ -1,4 +1,4 @@
-Description of HTML Purifier v1.6.0 library import into Moodle
+Description of HTML Purifier v1.6.1 library import into Moodle
 
 Changes:
  * Text.php - added nolink, tex and algebra tags