Skip to content
This repository has been archived by the owner on Nov 8, 2022. It is now read-only.

Commit

Permalink
Make forms work for transitional doctypes.
Browse files Browse the repository at this point in the history
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
  • Loading branch information
ezyang committed Dec 30, 2011
1 parent 1bbbc62 commit e0354fe
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 3 deletions.
1 change: 1 addition & 0 deletions NEWS
Expand Up @@ -23,6 +23,7 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
! Implement iframes, and allow them to be used in untrusted mode with
%HTML.SafeIframe and %URI.SafeIframeRegexp. Thanks Bradley M. Froehle
<brad.froehle@gmail.com> for submitting an initial version of the patch.
! The Forms module now works properly for transitional doctypes.
- Color keywords are now case insensitive. Thanks Yzmir Ramirez
<yramirez-htmlpurifier@adicio.com> for reporting.
- Explicitly initialize anonModule variable to null.
Expand Down
1 change: 1 addition & 0 deletions library/HTMLPurifier.includes.php
Expand Up @@ -73,6 +73,7 @@
require 'HTMLPurifier/VarParser.php';
require 'HTMLPurifier/VarParserException.php';
require 'HTMLPurifier/AttrDef/CSS.php';
require 'HTMLPurifier/AttrDef/Clone.php';
require 'HTMLPurifier/AttrDef/Enum.php';
require 'HTMLPurifier/AttrDef/Integer.php';
require 'HTMLPurifier/AttrDef/Lang.php';
Expand Down
1 change: 1 addition & 0 deletions library/HTMLPurifier.safe-includes.php
Expand Up @@ -67,6 +67,7 @@
require_once $__dir . '/HTMLPurifier/VarParser.php';
require_once $__dir . '/HTMLPurifier/VarParserException.php';
require_once $__dir . '/HTMLPurifier/AttrDef/CSS.php';
require_once $__dir . '/HTMLPurifier/AttrDef/Clone.php';
require_once $__dir . '/HTMLPurifier/AttrDef/Enum.php';
require_once $__dir . '/HTMLPurifier/AttrDef/Integer.php';
require_once $__dir . '/HTMLPurifier/AttrDef/Lang.php';
Expand Down
28 changes: 28 additions & 0 deletions library/HTMLPurifier/AttrDef/Clone.php
@@ -0,0 +1,28 @@
<?php

/**
* Dummy AttrDef that mimics another AttrDef, BUT it generates clones
* with make.
*/
class HTMLPurifier_AttrDef_Clone extends HTMLPurifier_AttrDef
{
/**
* What we're cloning
*/
protected $clone;

public function __construct($clone) {
$this->clone = $clone;
}

public function validate($v, $config, $context) {
return $this->clone->validate($v, $config, $context);
}

public function make($string) {
return clone $this->clone;
}

}

// vim: et sw=4 sts=4
14 changes: 14 additions & 0 deletions library/HTMLPurifier/AttrTypes.php
Expand Up @@ -15,6 +15,13 @@ class HTMLPurifier_AttrTypes
* types.
*/
public function __construct() {
// XXX This is kind of poor, since we don't actually /clone/
// instances; instead, we use the supplied make() attribute. So,
// the underlying class must know how to deal with arguments.
// With the old implementation of Enum, that ignored its
// arguments when handling a make dispatch, the IAlign
// definition wouldn't work.

// pseudo-types, must be instantiated via shorthand
$this->info['Enum'] = new HTMLPurifier_AttrDef_Enum();
$this->info['Bool'] = new HTMLPurifier_AttrDef_HTML_Bool();
Expand All @@ -29,6 +36,9 @@ public function __construct() {
$this->info['URI'] = new HTMLPurifier_AttrDef_URI();
$this->info['LanguageCode'] = new HTMLPurifier_AttrDef_Lang();
$this->info['Color'] = new HTMLPurifier_AttrDef_HTML_Color();
$this->info['IAlign'] = self::makeEnum('top,middle,bottom,left,right');
$this->info['LAlign'] = self::makeEnum('top,bottom,left,right');
$this->info['FrameTarget'] = new HTMLPurifier_AttrDef_HTML_FrameTarget();

// unimplemented aliases
$this->info['ContentType'] = new HTMLPurifier_AttrDef_Text();
Expand All @@ -44,6 +54,10 @@ public function __construct() {
$this->info['Number'] = new HTMLPurifier_AttrDef_Integer(false, false, true);
}

private static function makeEnum($in) {
return new HTMLPurifier_AttrDef_Clone(new HTMLPurifier_AttrDef_Enum(explode(',', $in)));
}

/**
* Retrieves a type
* @param $type String type name
Expand Down
3 changes: 2 additions & 1 deletion library/HTMLPurifier/HTMLModule/Forms.php
Expand Up @@ -84,7 +84,8 @@ public function setup($config) {
$button->excludes = $this->makeLookup(
'form', 'fieldset', // Form
'input', 'select', 'textarea', 'label', 'button', // Formctrl
'a' // as per HTML 4.01 spec, this is omitted by modularization
'a', // as per HTML 4.01 spec, this is omitted by modularization
'isindex', 'iframe' // legacy items
);

// Extra exclusion: img usemap="" is not permitted within this element.
Expand Down
18 changes: 17 additions & 1 deletion library/HTMLPurifier/HTMLModule/Legacy.php
Expand Up @@ -89,7 +89,7 @@ public function setup($config) {
$hr->attr['width'] = 'Length';

$img = $this->addBlankElement('img');
$img->attr['align'] = 'Enum#top,middle,bottom,left,right';
$img->attr['align'] = 'IAlign';
$img->attr['border'] = 'Pixels';
$img->attr['hspace'] = 'Pixels';
$img->attr['vspace'] = 'Pixels';
Expand Down Expand Up @@ -136,6 +136,22 @@ public function setup($config) {
$ul->attr['compact'] = 'Bool#compact';
$ul->attr['type'] = 'Enum#square,disc,circle';

// "safe" modifications to "unsafe" elements
// WARNING: If you want to add support for an unsafe, legacy
// attribute, make a new TrustedLegacy module with the trusted
// bit set appropriately

$form = $this->addBlankElement('form');
$form->content_model = 'Flow | #PCDATA';
$form->content_model_type = 'optional';
$form->attr['target'] = 'FrameTarget';

$input = $this->addBlankElement('input');
$input->attr['align'] = 'IAlign';

$legend = $this->addBlankElement('legend');
$legend->attr['align'] = 'LAlign';

}

}
Expand Down
7 changes: 7 additions & 0 deletions library/HTMLPurifier/HTMLModuleManager.php
Expand Up @@ -369,6 +369,13 @@ public function getElement($name, $trusted = null) {
// :TODO:
// non-standalone definitions that don't have a standalone
// to merge into could be deferred to the end
// HOWEVER, it is perfectly valid for a non-standalone
// definition to lack a standalone definition, even
// after all processing: this allows us to safely
// specify extra attributes for elements that may not be
// enabled all in one place. In particular, this might
// be the case for trusted elements. WARNING: care must
// be taken that the /extra/ definitions are all safe.
continue;
}

Expand Down
19 changes: 18 additions & 1 deletion tests/HTMLPurifier/HTMLModule/FormsTest.php
Expand Up @@ -7,10 +7,10 @@ function setUp() {
parent::setUp();
$this->config->set('HTML.Trusted', true);
$this->config->set('Attr.EnableID', true);
$this->config->set('Cache.DefinitionImpl', null);
}

function testBasicUse() {
$this->config->set('HTML.Doctype', 'HTML 4.01 Strict');
$this->assertResult( // need support for label for later
'
<form action="http://somesite.com/prog/adduser" method="post">
Expand All @@ -30,6 +30,7 @@ function testBasicUse() {
}

function testSelectOption() {
$this->config->set('HTML.Doctype', 'HTML 4.01 Strict');
$this->assertResult('
<form action="http://somesite.com/prog/component-select" method="post">
<p>
Expand All @@ -49,6 +50,7 @@ function testSelectOption() {
}

function testSelectOptgroup() {
$this->config->set('HTML.Doctype', 'HTML 4.01 Strict');
$this->assertResult('
<form action="http://somesite.com/prog/someprog" method="post">
<p>
Expand All @@ -74,6 +76,7 @@ function testSelectOptgroup() {
}

function testTextarea() {
$this->config->set('HTML.Doctype', 'HTML 4.01 Strict');
$this->assertResult('
<form action="http://somesite.com/prog/text-read" method="post">
<p>
Expand All @@ -90,6 +93,7 @@ function testTextarea() {
// label tests omitted

function testFieldset() {
$this->config->set('HTML.Doctype', 'HTML 4.01 Strict');
$this->assertResult('
<form action="..." method="post">
<fieldset>
Expand Down Expand Up @@ -122,17 +126,30 @@ function testFieldset() {
}

function testInputTransform() {
$this->config->set('HTML.Doctype', 'XHTML 1.0 Strict');
$this->assertResult('<input type="checkbox" />', '<input type="checkbox" value="" />');
}

function testTextareaTransform() {
$this->config->set('HTML.Doctype', 'HTML 4.01 Strict');
$this->assertResult('<textarea></textarea>', '<textarea cols="22" rows="3"></textarea>');
}

function testTextInFieldset() {
$this->config->set('HTML.Doctype', 'HTML 4.01 Strict');
$this->assertResult('<fieldset> <legend></legend>foo</fieldset>');
}

function testStrict() {
$this->config->set('HTML.Doctype', 'HTML 4.01 Strict');
$this->assertResult('<form action=""></form>', '');
}

function testLegacy() {
$this->assertResult('<form action=""></form>');
$this->assertResult('<form action=""><input align="left" /></form>');
}

}

// vim: et sw=4 sts=4

0 comments on commit e0354fe

Please sign in to comment.