diff --git a/NEWS b/NEWS
index ffa8f52e..225e65ca 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,10 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
- DefinitionCache no longer throws errors when it encounters old
serial files that do not conform to the current style
- Stray xmlns attributes removed from configuration documentation
+- configForm.php smoketest no longer has XSS vulnerability due to
+ unescaped print_r output
+- Printer adheres to configuration's directives on output format
+- Fix improperly named form field in ConfigForm printer
. Rewire some test-cases to swallow errors rather than expect them
. HTMLDefinition printer updated with some of the new attributes
. DefinitionCache keys reordered to reflect precedence: version number,
@@ -36,6 +40,13 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
. Directives now keep track of aliases to themselves
. Error collector now requires a severity to be passed, use PHP's internal
error constants for this
+. HTMLPurifier_Config::getAllowedDirectivesForForm implemented, allows
+ much easier selective embedding of configuration values
+. Doctype objects now accept public and system DTD identifiers
+. %HTML.Doctype is now constrained by specific values, to specify a custom
+ doctype use new %HTML.CustomDoctype
+. ConfigForm truncates long directives to keep the form small, and does
+ not re-output namespaces
2.0.0, released 2007-06-20
# Completely refactored HTMLModuleManager, decentralizing safety
diff --git a/library/HTMLPurifier/Config.php b/library/HTMLPurifier/Config.php
index 14da7dcd..d9b34c1e 100644
--- a/library/HTMLPurifier/Config.php
+++ b/library/HTMLPurifier/Config.php
@@ -341,25 +341,78 @@ class HTMLPurifier_Config
}
}
+ /**
+ * Returns a list of array(namespace, directive) for all directives
+ * that are allowed in a web-form context as per an allowed
+ * namespaces/directives list.
+ * @param $allowed List of allowed namespaces/directives
+ * @static
+ */
+ function getAllowedDirectivesForForm($allowed) {
+ $schema = HTMLPurifier_ConfigSchema::instance();
+ if ($allowed !== true) {
+ if (is_string($allowed)) $allowed = array($allowed);
+ $allowed_ns = array();
+ $allowed_directives = array();
+ $blacklisted_directives = array();
+ foreach ($allowed as $ns_or_directive) {
+ if (strpos($ns_or_directive, '.') !== false) {
+ // directive
+ if ($ns_or_directive[0] == '-') {
+ $blacklisted_directives[substr($ns_or_directive, 1)] = true;
+ } else {
+ $allowed_directives[$ns_or_directive] = true;
+ }
+ } else {
+ // namespace
+ $allowed_ns[$ns_or_directive] = true;
+ }
+ }
+ }
+ $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 ($def->class == 'alias') continue;
+ if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') continue;
+ $ret[] = array($ns, $directive);
+ }
+ }
+ return $ret;
+ }
+
/**
* Loads configuration values from $_GET/$_POST that were posted
* via ConfigForm
* @param $array $_GET or $_POST array to import
* @param $index Index/name that the config variables are in
+ * @param $allowed List of allowed namespaces/directives
* @param $mq_fix Boolean whether or not to enable magic quotes fix
* @static
*/
- function loadArrayFromForm($array, $index, $mq_fix = true) {
+ function loadArrayFromForm($array, $index, $allowed = true, $mq_fix = true) {
$array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array();
$mq = get_magic_quotes_gpc() && $mq_fix;
- foreach ($array as $key => $value) {
- if (!strncmp($key, 'Null_', 5) && !empty($value)) {
- unset($array[substr($key, 5)]);
- unset($array[$key]);
+
+ $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed);
+ $ret = array();
+ foreach ($allowed as $key) {
+ list($ns, $directive) = $key;
+ $skey = "$ns.$directive";
+ if (!empty($array["Null_$skey"])) {
+ $ret[$ns][$directive] = null;
+ continue;
}
- if ($mq) $array[$key] = stripslashes($value);
+ if (!isset($array[$skey])) continue;
+ $value = $mq ? stripslashes($array[$skey]) : $array[$skey];
+ $ret[$ns][$directive] = $value;
}
- return @HTMLPurifier_Config::create($array);
+
+ $config = HTMLPurifier_Config::create($ret);
+ return $config;
}
/**
diff --git a/library/HTMLPurifier/Doctype.php b/library/HTMLPurifier/Doctype.php
index d6e2c4ab..8fee70c4 100644
--- a/library/HTMLPurifier/Doctype.php
+++ b/library/HTMLPurifier/Doctype.php
@@ -34,23 +34,33 @@ class HTMLPurifier_Doctype
*/
var $aliases = array();
+ /**
+ * Public DTD identifier
+ */
+ var $dtdPublic;
+
+ /**
+ * System DTD identifier
+ */
+ var $dtdSystem;
+
function HTMLPurifier_Doctype($name = null, $xml = true, $modules = array(),
- $tidyModules = array(), $aliases = array()
+ $tidyModules = array(), $aliases = array(), $dtd_public = null, $dtd_system = null
) {
$this->name = $name;
$this->xml = $xml;
$this->modules = $modules;
$this->tidyModules = $tidyModules;
$this->aliases = $aliases;
+ $this->dtdPublic = $dtd_public;
+ $this->dtdSystem = $dtd_system;
}
/**
* Clones the doctype, use before resolving modes and the like
*/
function copy() {
- return new HTMLPurifier_Doctype(
- $this->name, $this->xml, $this->modules, $this->tidyModules, $this->aliases
- );
+ return unserialize(serialize($this));
}
}
diff --git a/library/HTMLPurifier/DoctypeRegistry.php b/library/HTMLPurifier/DoctypeRegistry.php
index 57ccd506..52d0a706 100644
--- a/library/HTMLPurifier/DoctypeRegistry.php
+++ b/library/HTMLPurifier/DoctypeRegistry.php
@@ -44,14 +44,14 @@ class HTMLPurifier_DoctypeRegistry
* @return Reference to registered doctype (usable for further editing)
*/
function ®ister($doctype, $xml = true, $modules = array(),
- $tidy_modules = array(), $aliases = array()
+ $tidy_modules = array(), $aliases = array(), $dtd_public = null, $dtd_system = null
) {
if (!is_array($modules)) $modules = array($modules);
if (!is_array($tidy_modules)) $tidy_modules = array($tidy_modules);
if (!is_array($aliases)) $aliases = array($aliases);
if (!is_object($doctype)) {
$doctype = new HTMLPurifier_Doctype(
- $doctype, $xml, $modules, $tidy_modules, $aliases
+ $doctype, $xml, $modules, $tidy_modules, $aliases, $dtd_public, $dtd_system
);
}
$this->doctypes[$doctype->name] =& $doctype;
@@ -76,7 +76,7 @@ class HTMLPurifier_DoctypeRegistry
function &get($doctype) {
if (isset($this->aliases[$doctype])) $doctype = $this->aliases[$doctype];
if (!isset($this->doctypes[$doctype])) {
- trigger_error('Doctype ' . htmlspecialchars($doctype) . ' does not exist');
+ trigger_error('Doctype ' . htmlspecialchars($doctype) . ' does not exist', E_USER_ERROR);
$anon = new HTMLPurifier_Doctype($doctype);
return $anon;
}
@@ -103,9 +103,9 @@ class HTMLPurifier_DoctypeRegistry
function getDoctypeFromConfig($config) {
// recommended test
$doctype = $config->get('HTML', 'Doctype');
- if ($doctype !== null) {
- return $doctype;
- }
+ if (!empty($doctype)) return $doctype;
+ $doctype = $config->get('HTML', 'CustomDoctype');
+ if (!empty($doctype)) return $doctype;
// backwards-compatibility
if ($config->get('HTML', 'XHTML')) {
$doctype = 'XHTML 1.0';
diff --git a/library/HTMLPurifier/HTMLModuleManager.php b/library/HTMLPurifier/HTMLModuleManager.php
index c46a8b2c..8bc11592 100644
--- a/library/HTMLPurifier/HTMLModuleManager.php
+++ b/library/HTMLPurifier/HTMLModuleManager.php
@@ -37,14 +37,27 @@ require_once 'HTMLPurifier/HTMLModule/Tidy/XHTMLStrict.php';
require_once 'HTMLPurifier/HTMLModule/Tidy/Proprietary.php';
HTMLPurifier_ConfigSchema::define(
- 'HTML', 'Doctype', null, 'string/null',
- 'Doctype to use, pre-defined values are HTML 4.01 Transitional, HTML 4.01 '.
- 'Strict, XHTML 1.0 Transitional, XHTML 1.0 Strict, XHTML 1.1. '.
+ 'HTML', 'Doctype', '', 'string',
+ 'Doctype to use during filtering. '.
'Technically speaking this is not actually a doctype (as it does '.
'not identify a corresponding DTD), but we are using this name '.
- 'for sake of simplicity. This will override any older directives '.
+ 'for sake of simplicity. When non-blank, this will override any older directives '.
'like %HTML.XHTML or %HTML.Strict.'
);
+HTMLPurifier_ConfigSchema::defineAllowedValues('HTML', 'Doctype', array(
+ '', 'HTML 4.01 Transitional', 'HTML 4.01 Strict',
+ 'XHTML 1.0 Transitional', 'XHTML 1.0 Strict',
+ 'XHTML 1.1'
+));
+
+HTMLPurifier_ConfigSchema::define(
+ 'HTML', 'CustomDoctype', null, 'string/null',
+'
+A custom doctype for power-users who defined there own document
+type. This directive only applies when %HTML.Doctype is blank.
+This directive has been available since 2.0.1.
+'
+);
HTMLPurifier_ConfigSchema::define(
'HTML', 'Trusted', false, 'bool',
@@ -167,31 +180,46 @@ class HTMLPurifier_HTMLModuleManager
$this->doctypes->register(
'HTML 4.01 Transitional', false,
array_merge($common, $transitional, $non_xml),
- array('Tidy_Transitional', 'Tidy_Proprietary')
+ array('Tidy_Transitional', 'Tidy_Proprietary'),
+ array(),
+ '-//W3C//DTD HTML 4.01 Transitional//EN',
+ 'http://www.w3.org/TR/html4/loose.dtd'
);
$this->doctypes->register(
'HTML 4.01 Strict', false,
array_merge($common, $non_xml),
- array('Tidy_Strict', 'Tidy_Proprietary')
+ array('Tidy_Strict', 'Tidy_Proprietary'),
+ array(),
+ '-//W3C//DTD HTML 4.01//EN',
+ 'http://www.w3.org/TR/html4/strict.dtd'
);
$this->doctypes->register(
'XHTML 1.0 Transitional', true,
array_merge($common, $transitional, $xml, $non_xml),
- array('Tidy_Transitional', 'Tidy_XHTML', 'Tidy_Proprietary')
+ array('Tidy_Transitional', 'Tidy_XHTML', 'Tidy_Proprietary'),
+ array(),
+ '-//W3C//DTD XHTML 1.0 Transitional//EN',
+ 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'
);
$this->doctypes->register(
'XHTML 1.0 Strict', true,
array_merge($common, $xml, $non_xml),
- array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_XHTMLStrict', 'Tidy_Proprietary')
+ array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_XHTMLStrict', 'Tidy_Proprietary'),
+ array(),
+ '-//W3C//DTD XHTML 1.0 Strict//EN',
+ 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'
);
$this->doctypes->register(
'XHTML 1.1', true,
array_merge($common, $xml),
- array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_Proprietary') // Tidy_XHTML1_1
+ array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_Proprietary'), // Tidy_XHTML1_1
+ array(),
+ '-//W3C//DTD XHTML 1.1//EN',
+ 'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd'
);
}
diff --git a/library/HTMLPurifier/Printer.php b/library/HTMLPurifier/Printer.php
index 95be17a2..8fa23f5e 100644
--- a/library/HTMLPurifier/Printer.php
+++ b/library/HTMLPurifier/Printer.php
@@ -26,6 +26,16 @@ class HTMLPurifier_Printer
$this->generator = new HTMLPurifier_Generator();
}
+ /**
+ * Give generator necessary configuration if possible
+ */
+ function prepareGenerator($config) {
+ // hack for smoketests/configForm.php
+ if (empty($config->conf['HTML'])) return;
+ $context = new HTMLPurifier_Context();
+ $this->generator->generateFromTokens(array(), $config, $context);
+ }
+
/**
* Main function that renders object or aspect of that object
* @note Parameters vary depending on printer
diff --git a/library/HTMLPurifier/Printer/ConfigForm.php b/library/HTMLPurifier/Printer/ConfigForm.php
index c157f2ab..c57f0bbe 100644
--- a/library/HTMLPurifier/Printer/ConfigForm.php
+++ b/library/HTMLPurifier/Printer/ConfigForm.php
@@ -38,18 +38,19 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
/**
* Returns HTML output for a configuration form
* @param $config Configuration object of current form state
- * @param $ns Optional namespace(s) to restrict form to
+ * @param $allowed Optional namespace(s) and directives to restrict form to.
*/
- function render($config, $ns = true) {
+ function render($config, $allowed = true, $render_controls = true) {
$this->config = $config;
- if ($ns === true) {
- $all = $config->getAll();
- } else {
- if (is_string($ns)) $ns = array($ns);
- foreach ($ns as $n) {
- $all = array($n => $config->getBatch($n));
- }
+ $this->prepareGenerator($config);
+
+ $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed);
+ $all = array();
+ foreach ($allowed as $key) {
+ list($ns, $directive) = $key;
+ $all[$ns][$directive] = $config->get($ns, $directive);
}
+
$ret = '';
$ret .= $this->start('table', array('class' => 'hp-config'));
$ret .= $this->start('thead');
@@ -61,13 +62,16 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
foreach ($all as $ns => $directives) {
$ret .= $this->renderNamespace($ns, $directives);
}
- $ret .= $this->start('tfoot');
- $ret .= $this->start('tr');
- $ret .= $this->start('td', array('colspan' => 2, 'class' => 'controls'));
- $ret .= ' [Reset]';
- $ret .= $this->end('td');
- $ret .= $this->end('tr');
- $ret .= $this->end('tfoot');
+ if ($render_controls) {
+ $ret .= $this->start('tfoot');
+ $ret .= $this->start('tr');
+ $ret .= $this->start('td', array('colspan' => 2, 'class' => 'controls'));
+ $ret .= $this->elementEmpty('input', array('type' => 'Submit', 'value' => 'Submit'));
+ $ret .= '[Reset]';
+ $ret .= $this->end('td');
+ $ret .= $this->end('tr');
+ $ret .= $this->end('tfoot');
+ }
$ret .= $this->end('table');
return $ret;
}
@@ -93,11 +97,20 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
$url = str_replace('%s', urlencode("$ns.$directive"), $this->docURL);
$ret .= $this->start('a', array('href' => $url));
}
+ $attr = array('for' => "{$this->name}:$ns.$directive");
+ // crop directive name if it's too long
+ if (strlen($directive) < 14) {
+ $directive_disp = $directive;
+ } else {
+ $directive_disp = substr($directive, 0, 12) . '...';
+ $attr['title'] = $directive;
+ }
+
$ret .= $this->element(
'label',
- "%$ns.$directive",
+ $directive_disp,
// component printers must create an element with this id
- array('for' => "{$this->name}:$ns.$directive")
+ $attr
);
if ($this->docURL) $ret .= $this->end('a');
$ret .= $this->end('th');
@@ -136,6 +149,7 @@ class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer
$this->obj = $obj;
}
function render($ns, $directive, $value, $name, $config) {
+ $this->prepareGenerator($config);
$ret = '';
$ret .= $this->start('label', array('for' => "$name:Null_$ns.$directive"));
$ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose'));
@@ -145,7 +159,7 @@ class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer
'type' => 'checkbox',
'value' => '1',
'class' => 'null-toggle',
- 'name' => "$name:Null_$ns.$directive",
+ 'name' => "$name"."[Null_$ns.$directive]",
'id' => "$name:Null_$ns.$directive",
'onclick' => "toggleWriteability('$name:$ns.$directive',checked)" // INLINE JAVASCRIPT!!!!
);
@@ -163,6 +177,7 @@ class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer
*/
class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
function render($ns, $directive, $value, $name, $config) {
+ $this->prepareGenerator($config);
// this should probably be split up a little
$ret = '';
$def = $config->def->info[$ns][$directive];
@@ -193,7 +208,6 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
$value = serialize($value);
}
$attr = array(
- 'type' => 'text',
'name' => "$name"."[$ns.$directive]",
'id' => "$name:$ns.$directive"
);
@@ -208,6 +222,7 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
$ret .= $this->end('select');
} else {
$attr['value'] = $value;
+ $attr['type'] = 'text';
$ret .= $this->elementEmpty('input', $attr);
}
return $ret;
@@ -219,8 +234,8 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
*/
class HTMLPurifier_Printer_ConfigForm_bool extends HTMLPurifier_Printer {
function render($ns, $directive, $value, $name, $config) {
+ $this->prepareGenerator($config);
$ret = '';
-
$ret .= $this->start('div', array('id' => "$name:$ns.$directive"));
$ret .= $this->start('label', array('for' => "$name:Yes_$ns.$directive"));
diff --git a/smoketests/printDefinition.php b/smoketests/printDefinition.php
index 771d03bb..b82e79e0 100644
--- a/smoketests/printDefinition.php
+++ b/smoketests/printDefinition.php
@@ -6,7 +6,7 @@ require_once 'HTMLPurifier/Printer/HTMLDefinition.php';
require_once 'HTMLPurifier/Printer/CSSDefinition.php';
require_once 'HTMLPurifier/Printer/ConfigForm.php';
-$config = HTMLPurifier_Config::loadArrayFromForm($_GET, 'config');
+$config = HTMLPurifier_Config::loadArrayFromForm($_GET, 'config', 'HTML');
// you can do custom configuration!
if (file_exists('printDefinition.settings.php')) {
@@ -22,6 +22,7 @@ $printer_config_form = new HTMLPurifier_Printer_ConfigForm(
);
echo '';
+
?>
diff --git a/smoketests/testSchema.php b/smoketests/testSchema.php
index 1295566e..f2e8e3bf 100644
--- a/smoketests/testSchema.php
+++ b/smoketests/testSchema.php
@@ -5,40 +5,36 @@ $custom_schema = new HTMLPurifier_ConfigSchema();
$old = HTMLPurifier_ConfigSchema::instance();
$custom_schema =& HTMLPurifier_ConfigSchema::instance($custom_schema);
-if (!class_exists('CS')) {
- class CS extends HTMLPurifier_ConfigSchema {}
-}
+HTMLPurifier_ConfigSchema::defineNamespace('Element', 'Chemical substances that cannot be further decomposed');
-CS::defineNamespace('Element', 'Chemical substances that cannot be further decomposed');
-
-CS::define('Element', 'Abbr', 'H', 'string', 'Abbreviation of element name.');
-CS::define('Element', 'Name', 'hydrogen', 'istring', 'Full name of atoms.');
-CS::define('Element', 'Number', 1, 'int', 'Atomic number, is identity.');
-CS::define('Element', 'Mass', 1.00794, 'float', 'Atomic mass.');
-CS::define('Element', 'Radioactive', false, 'bool', 'Does it have rapid decay?');
-CS::define('Element', 'Isotopes', array('1' => true, '2' => true, '3' => true), 'lookup',
+HTMLPurifier_ConfigSchema::define('Element', 'Abbr', 'H', 'string', 'Abbreviation of element name.');
+HTMLPurifier_ConfigSchema::define('Element', 'Name', 'hydrogen', 'istring', 'Full name of atoms.');
+HTMLPurifier_ConfigSchema::define('Element', 'Number', 1, 'int', 'Atomic number, is identity.');
+HTMLPurifier_ConfigSchema::define('Element', 'Mass', 1.00794, 'float', 'Atomic mass.');
+HTMLPurifier_ConfigSchema::define('Element', 'Radioactive', false, 'bool', 'Does it have rapid decay?');
+HTMLPurifier_ConfigSchema::define('Element', 'Isotopes', array('1' => true, '2' => true, '3' => true), 'lookup',
'What numbers of neutrons for this element have been observed?');
-CS::define('Element', 'Traits', array('nonmetallic', 'odorless', 'flammable'), 'list',
+HTMLPurifier_ConfigSchema::define('Element', 'Traits', array('nonmetallic', 'odorless', 'flammable'), 'list',
'What are general properties of the element?');
-CS::define('Element', 'IsotopeNames', array('1' => 'protium', '2' => 'deuterium', '3' => 'tritium'), 'hash',
+HTMLPurifier_ConfigSchema::define('Element', 'IsotopeNames', array('1' => 'protium', '2' => 'deuterium', '3' => 'tritium'), 'hash',
'Lookup hash of neutron counts to formal names.');
-CS::defineNamespace('Instrument', 'Of the musical type.');
+HTMLPurifier_ConfigSchema::defineNamespace('Instrument', 'Of the musical type.');
-CS::define('Instrument', 'Manufacturer', 'Yamaha', 'string', 'Who made it?');
-CS::defineAllowedValues('Instrument', 'Manufacturer', array(
+HTMLPurifier_ConfigSchema::define('Instrument', 'Manufacturer', 'Yamaha', 'string', 'Who made it?');
+HTMLPurifier_ConfigSchema::defineAllowedValues('Instrument', 'Manufacturer', array(
'Yamaha', 'Conn-Selmer', 'Vandoren', 'Laubin', 'Buffet', 'other'));
-CS::defineValueAliases('Instrument', 'Manufacturer', array(
+HTMLPurifier_ConfigSchema::defineValueAliases('Instrument', 'Manufacturer', array(
'Selmer' => 'Conn-Selmer'));
-CS::define('Instrument', 'Family', 'woodwind', 'istring', 'What family is it?');
-CS::defineAllowedValues('Instrument', 'Family', array(
+HTMLPurifier_ConfigSchema::define('Instrument', 'Family', 'woodwind', 'istring', 'What family is it?');
+HTMLPurifier_ConfigSchema::defineAllowedValues('Instrument', 'Family', array(
'brass', 'woodwind', 'percussion', 'string', 'keyboard', 'electronic'));
-CS::defineValueAliases('Instrument', 'Family', array(
+HTMLPurifier_ConfigSchema::defineValueAliases('Instrument', 'Family', array(
'synth' => 'electronic'));
-CS::defineNamespace('ReportCard', 'It is for grades.');
-CS::define('ReportCard', 'English', null, 'string/null', 'Grade from English class.');
-CS::define('ReportCard', 'Absences', 0, 'int', 'How many times missing from school?');
+HTMLPurifier_ConfigSchema::defineNamespace('ReportCard', 'It is for grades.');
+HTMLPurifier_ConfigSchema::define('ReportCard', 'English', null, 'string/null', 'Grade from English class.');
+HTMLPurifier_ConfigSchema::define('ReportCard', 'Absences', 0, 'int', 'How many times missing from school?');
?>
\ No newline at end of file
diff --git a/tests/HTMLPurifier/ConfigTest.php b/tests/HTMLPurifier/ConfigTest.php
index 787253f0..72023e5e 100644
--- a/tests/HTMLPurifier/ConfigTest.php
+++ b/tests/HTMLPurifier/ConfigTest.php
@@ -376,6 +376,84 @@ class HTMLPurifier_ConfigTest extends UnitTestCase
}
+ function test_loadArrayFromForm() {
+
+ CS::defineNamespace('Pancake', 'This should not be user customizable');
+ CS::define('Pancake', 'Mix', 'buttermilk', 'string', 'Type of pancake mix to use.');
+ CS::define('Pancake', 'Served', true, 'bool', 'But this is customizable by user.');
+ CS::defineNamespace('Toppings', 'This is user customizable');
+ CS::define('Toppings', 'Syrup', true, 'bool', 'Absolutely standard!');
+ CS::define('Toppings', 'Flavor', 'maple', 'string', 'What flavor is the syrup?');
+ CS::define('Toppings', 'Strawberries', 3, 'int', 'Quite delightful fruit.');
+ CS::define('Toppings', 'Calories', 2000, 'int/null', 'Some things are best left unknown.');
+ CS::define('Toppings', 'DefinitionID', null, 'string/null', 'Do not let this be set');
+ CS::define('Toppings', 'DefinitionRev', 1, 'int', 'Do not let this be set');
+ CS::define('Toppings', 'Protected', 1, 'int', 'Do not let this be set');
+
+ $get = array(
+ 'breakfast' => array(
+ 'Pancake.Mix' => 'nasty',
+ 'Pancake.Served' => '0',
+ 'Toppings.Syrup' => '0',
+ 'Toppings.Flavor' => "Bug\\'s juice",
+ 'Toppings.Strawberries' => '999',
+ 'Toppings.Calories' => '',
+ 'Null_Toppings.Calories' => '1',
+ 'Toppings.DefinitionID' => '',
+ 'Toppings.DefinitionRev' => '65',
+ 'Toppings.Protected' => '4',
+ )
+ );
+
+ $config_expect = HTMLPurifier_Config::create(array(
+ 'Pancake.Served' => false,
+ 'Toppings.Syrup' => false,
+ 'Toppings.Flavor' => "Bug's juice",
+ 'Toppings.Strawberries' => 999,
+ 'Toppings.Calories' => null
+ ));
+
+ $config_result = HTMLPurifier_Config::loadArrayFromForm($get, 'breakfast', array('Pancake.Served', 'Toppings', '-Toppings.Protected'), true);
+
+ $this->assertEqual($config_expect, $config_result);
+
+
+ $get = array(
+ 'breakfast' => array(
+ 'Pancake.Mix' => 'n\\asty'
+ )
+ );
+ $config_expect = HTMLPurifier_Config::create(array(
+ 'Pancake.Mix' => 'n\\asty'
+ ));
+ $config_result = HTMLPurifier_Config::loadArrayFromForm($get, 'breakfast', true, false);
+ $this->assertEqual($config_expect, $config_result);
+
+ }
+
+ function test_getAllowedDirectivesForForm() {
+ CS::defineNamespace('Unused', 'Not mentioned, so deny');
+ CS::define('Unused', 'Unused', 'Foobar', 'string', 'Not mentioned, do not allow');
+ CS::defineNamespace('Partial', 'Some are mentioned, allow only those');
+ CS::define('Partial', 'Allowed', true, 'bool', 'Mentioned, allowed');
+ CS::define('Partial', 'Unused', 'Foobar', 'string', 'Not mentioned, do not allow');
+ CS::defineNamespace('All', 'Entire namespace allowed, allow all unless...');
+ CS::define('All', 'Allowed', true, 'bool', 'Not mentioned, allowed');
+ CS::define('All', 'Blacklisted', 'Foobar', 'string', 'Specifically blacklisted');
+ CS::define('All', 'DefinitionID', 'Foobar', 'string/null', 'Special case, auto-blacklisted');
+ CS::define('All', 'DefinitionRev', 2, 'int', 'Special case, auto-blacklisted');
+
+ $input = array('Partial.Allowed', 'All', '-All.Blacklisted');
+ $output = HTMLPurifier_Config::getAllowedDirectivesForForm($input);
+ $expect = array(
+ array('Partial', 'Allowed'),
+ array('All', 'Allowed')
+ );
+
+ $this->assertEqual($output, $expect);
+
+ }
+
}
?>
\ No newline at end of file
diff --git a/tests/HTMLPurifier/HTMLModuleManagerTest.php b/tests/HTMLPurifier/HTMLModuleManagerTest.php
index 4f94bc1b..b74df5f4 100644
--- a/tests/HTMLPurifier/HTMLModuleManagerTest.php
+++ b/tests/HTMLPurifier/HTMLModuleManagerTest.php
@@ -38,7 +38,7 @@ class HTMLPurifier_HTMLModuleManagerTest extends UnitTestCase
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML', 'Trusted', false);
- $config->set('HTML', 'Doctype', 'Blank');
+ $config->set('HTML', 'CustomDoctype', 'Blank');
$manager->setup($config);
@@ -94,7 +94,7 @@ class HTMLPurifier_HTMLModuleManagerTest extends UnitTestCase
$manager->registerModule($magic_module);
$config = HTMLPurifier_Config::create(array(
- 'HTML.Doctype' => 'Fantasy Inventory 1.0',
+ 'HTML.CustomDoctype' => 'Fantasy Inventory 1.0',
'HTML.AllowedModules' => 'Weapons'
));
$manager->setup($config);