forked from GNUsocial/gnu-social
HTMLPurifier defangs arbitrary submitted HTML. We're using it in the OStatus plugin, but it may be valuable for other parts of the codebase (I think OEmbed might benefit, for example).
156 lines
5.2 KiB
PHP
156 lines
5.2 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @todo Unit test
|
|
*/
|
|
class HTMLPurifier_ContentSets
|
|
{
|
|
|
|
/**
|
|
* List of content set strings (pipe seperators) indexed by name.
|
|
*/
|
|
public $info = array();
|
|
|
|
/**
|
|
* List of content set lookups (element => true) indexed by name.
|
|
* @note This is in HTMLPurifier_HTMLDefinition->info_content_sets
|
|
*/
|
|
public $lookup = array();
|
|
|
|
/**
|
|
* Synchronized list of defined content sets (keys of info)
|
|
*/
|
|
protected $keys = array();
|
|
/**
|
|
* Synchronized list of defined content values (values of info)
|
|
*/
|
|
protected $values = array();
|
|
|
|
/**
|
|
* Merges in module's content sets, expands identifiers in the content
|
|
* sets and populates the keys, values and lookup member variables.
|
|
* @param $modules List of HTMLPurifier_HTMLModule
|
|
*/
|
|
public function __construct($modules) {
|
|
if (!is_array($modules)) $modules = array($modules);
|
|
// populate content_sets based on module hints
|
|
// sorry, no way of overloading
|
|
foreach ($modules as $module_i => $module) {
|
|
foreach ($module->content_sets as $key => $value) {
|
|
$temp = $this->convertToLookup($value);
|
|
if (isset($this->lookup[$key])) {
|
|
// add it into the existing content set
|
|
$this->lookup[$key] = array_merge($this->lookup[$key], $temp);
|
|
} else {
|
|
$this->lookup[$key] = $temp;
|
|
}
|
|
}
|
|
}
|
|
$old_lookup = false;
|
|
while ($old_lookup !== $this->lookup) {
|
|
$old_lookup = $this->lookup;
|
|
foreach ($this->lookup as $i => $set) {
|
|
$add = array();
|
|
foreach ($set as $element => $x) {
|
|
if (isset($this->lookup[$element])) {
|
|
$add += $this->lookup[$element];
|
|
unset($this->lookup[$i][$element]);
|
|
}
|
|
}
|
|
$this->lookup[$i] += $add;
|
|
}
|
|
}
|
|
|
|
foreach ($this->lookup as $key => $lookup) {
|
|
$this->info[$key] = implode(' | ', array_keys($lookup));
|
|
}
|
|
$this->keys = array_keys($this->info);
|
|
$this->values = array_values($this->info);
|
|
}
|
|
|
|
/**
|
|
* Accepts a definition; generates and assigns a ChildDef for it
|
|
* @param $def HTMLPurifier_ElementDef reference
|
|
* @param $module Module that defined the ElementDef
|
|
*/
|
|
public function generateChildDef(&$def, $module) {
|
|
if (!empty($def->child)) return; // already done!
|
|
$content_model = $def->content_model;
|
|
if (is_string($content_model)) {
|
|
// Assume that $this->keys is alphanumeric
|
|
$def->content_model = preg_replace_callback(
|
|
'/\b(' . implode('|', $this->keys) . ')\b/',
|
|
array($this, 'generateChildDefCallback'),
|
|
$content_model
|
|
);
|
|
//$def->content_model = str_replace(
|
|
// $this->keys, $this->values, $content_model);
|
|
}
|
|
$def->child = $this->getChildDef($def, $module);
|
|
}
|
|
|
|
public function generateChildDefCallback($matches) {
|
|
return $this->info[$matches[0]];
|
|
}
|
|
|
|
/**
|
|
* Instantiates a ChildDef based on content_model and content_model_type
|
|
* member variables in HTMLPurifier_ElementDef
|
|
* @note This will also defer to modules for custom HTMLPurifier_ChildDef
|
|
* subclasses that need content set expansion
|
|
* @param $def HTMLPurifier_ElementDef to have ChildDef extracted
|
|
* @return HTMLPurifier_ChildDef corresponding to ElementDef
|
|
*/
|
|
public function getChildDef($def, $module) {
|
|
$value = $def->content_model;
|
|
if (is_object($value)) {
|
|
trigger_error(
|
|
'Literal object child definitions should be stored in '.
|
|
'ElementDef->child not ElementDef->content_model',
|
|
E_USER_NOTICE
|
|
);
|
|
return $value;
|
|
}
|
|
switch ($def->content_model_type) {
|
|
case 'required':
|
|
return new HTMLPurifier_ChildDef_Required($value);
|
|
case 'optional':
|
|
return new HTMLPurifier_ChildDef_Optional($value);
|
|
case 'empty':
|
|
return new HTMLPurifier_ChildDef_Empty();
|
|
case 'custom':
|
|
return new HTMLPurifier_ChildDef_Custom($value);
|
|
}
|
|
// defer to its module
|
|
$return = false;
|
|
if ($module->defines_child_def) { // save a func call
|
|
$return = $module->getChildDef($def);
|
|
}
|
|
if ($return !== false) return $return;
|
|
// error-out
|
|
trigger_error(
|
|
'Could not determine which ChildDef class to instantiate',
|
|
E_USER_ERROR
|
|
);
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Converts a string list of elements separated by pipes into
|
|
* a lookup array.
|
|
* @param $string List of elements
|
|
* @return Lookup array of elements
|
|
*/
|
|
protected function convertToLookup($string) {
|
|
$array = explode('|', str_replace(' ', '', $string));
|
|
$ret = array();
|
|
foreach ($array as $i => $k) {
|
|
$ret[$k] = true;
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
}
|
|
|
|
// vim: et sw=4 sts=4
|