104 if (!isset($module->info[$element_name])) {
105 $element = $module->addBlankElement($element_name);
107 $element = $module->info[$element_name];
109 $element->attr[$attr_name] = $def;
117 public function addElement($element_name,
$type, $contents, $attr_collections, $attributes = array()) {
121 $element = $module->addElement($element_name,
$type, $contents, $attr_collections, $attributes);
133 $element = $module->addBlankElement($element_name);
143 if (!$this->_anonModule) {
145 $this->_anonModule->name =
'Anonymous';
168 unset($this->manager);
171 foreach ($this->info as $k => $v) {
172 unset($this->info[$k]->content_model);
173 unset($this->info[$k]->content_model_type);
182 if ($this->_anonModule) {
186 $this->manager->addModule($this->_anonModule);
187 unset($this->_anonModule);
190 $this->manager->setup(
$config);
191 $this->doctype = $this->manager->doctype;
193 foreach ($this->manager->modules as $module) {
194 foreach($module->info_tag_transform as $k => $v) {
195 if ($v ===
false) unset($this->info_tag_transform[$k]);
196 else $this->info_tag_transform[$k] = $v;
198 foreach($module->info_attr_transform_pre as $k => $v) {
199 if ($v ===
false) unset($this->info_attr_transform_pre[$k]);
200 else $this->info_attr_transform_pre[$k] = $v;
202 foreach($module->info_attr_transform_post as $k => $v) {
203 if ($v ===
false) unset($this->info_attr_transform_post[$k]);
204 else $this->info_attr_transform_post[$k] = $v;
206 foreach ($module->info_injector as $k => $v) {
207 if ($v ===
false) unset($this->info_injector[$k]);
208 else $this->info_injector[$k] = $v;
212 $this->info = $this->manager->getElements();
213 $this->info_content_sets = $this->manager->contentSets->lookup;
222 $block_wrapper =
$config->get(
'HTML.BlockWrapper');
223 if (isset($this->info_content_sets[
'Block'][$block_wrapper])) {
224 $this->info_block_wrapper = $block_wrapper;
226 trigger_error(
'Cannot use non-block element as block wrapper',
230 $parent =
$config->get(
'HTML.Parent');
231 $def = $this->manager->getElement($parent,
true);
233 $this->info_parent = $parent;
234 $this->info_parent_def = $def;
236 trigger_error(
'Cannot use unrecognized element as parent',
238 $this->info_parent_def = $this->manager->getElement($this->info_parent,
true);
242 $support =
"(for information on implementing this, see the ".
247 $allowed_elements =
$config->get(
'HTML.AllowedElements');
248 $allowed_attributes =
$config->get(
'HTML.AllowedAttributes');
250 if (!is_array($allowed_elements) && !is_array($allowed_attributes)) {
251 $allowed =
$config->get(
'HTML.Allowed');
252 if (is_string($allowed)) {
257 if (is_array($allowed_elements)) {
258 foreach ($this->info as
$name =>
$d) {
259 if(!isset($allowed_elements[
$name])) unset($this->info[$name]);
260 unset($allowed_elements[$name]);
263 foreach ($allowed_elements as $element =>
$d) {
264 $element = htmlspecialchars($element);
265 trigger_error(
"Element '$element' is not supported $support", E_USER_WARNING);
271 $allowed_attributes_mutable = $allowed_attributes;
272 if (is_array($allowed_attributes)) {
277 foreach ($this->info_global_attr as $attr =>
$x) {
278 $keys = array($attr,
"*@$attr",
"*.$attr");
280 foreach ($keys as $key) {
281 if ($delete && isset($allowed_attributes[$key])) {
284 if (isset($allowed_attributes_mutable[$key])) {
285 unset($allowed_attributes_mutable[$key]);
288 if ($delete) unset($this->info_global_attr[$attr]);
291 foreach ($this->info as $tag =>
$info) {
292 foreach (
$info->attr as $attr =>
$x) {
293 $keys = array(
"$tag@$attr", $attr,
"*@$attr",
"$tag.$attr",
"*.$attr");
295 foreach ($keys as $key) {
296 if ($delete && isset($allowed_attributes[$key])) {
299 if (isset($allowed_attributes_mutable[$key])) {
300 unset($allowed_attributes_mutable[$key]);
303 if ($delete) unset($this->info[$tag]->attr[$attr]);
307 foreach ($allowed_attributes_mutable as $elattr =>
$d) {
308 $bits = preg_split(
'/[.@]/', $elattr, 2);
312 if ($bits[0] !==
'*') {
313 $element = htmlspecialchars($bits[0]);
314 $attribute = htmlspecialchars($bits[1]);
315 if (!isset($this->info[$element])) {
316 trigger_error(
"Cannot allow attribute '$attribute' if element '$element' is not allowed/supported $support");
318 trigger_error(
"Attribute '$attribute' in element '$element' not supported $support",
325 $attribute = htmlspecialchars($bits[0]);
326 trigger_error(
"Global attribute '$attribute' is not ".
327 "supported in any elements $support",
337 $forbidden_elements =
$config->get(
'HTML.ForbiddenElements');
338 $forbidden_attributes =
$config->get(
'HTML.ForbiddenAttributes');
340 foreach ($this->info as $tag =>
$info) {
341 if (isset($forbidden_elements[$tag])) {
342 unset($this->info[$tag]);
345 foreach (
$info->attr as $attr =>
$x) {
347 isset($forbidden_attributes[
"$tag@$attr"]) ||
348 isset($forbidden_attributes[
"*@$attr"]) ||
349 isset($forbidden_attributes[$attr])
351 unset($this->info[$tag]->attr[$attr]);
354 elseif (isset($forbidden_attributes[
"$tag.$attr"])) {
356 trigger_error(
"Error with $tag.$attr: tag.attr syntax not supported for HTML.ForbiddenAttributes; use tag@attr instead", E_USER_WARNING);
360 foreach ($forbidden_attributes as $key => $v) {
361 if (strlen($key) < 2)
continue;
362 if ($key[0] !=
'*')
continue;
363 if ($key[1] ==
'.') {
364 trigger_error(
"Error with $key: *.attr syntax not supported for HTML.ForbiddenAttributes; use attr instead", E_USER_WARNING);
369 foreach ($this->info_injector as $i => $injector) {
370 if ($injector->checkNeeded(
$config) !==
false) {
373 unset($this->info_injector[$i]);
389 $list = str_replace(array(
' ',
"\t"),
'', $list);
392 $attributes = array();
394 $chunks = preg_split(
'/(,|[\n\r]+)/', $list);
395 foreach ($chunks as $chunk) {
396 if (empty($chunk))
continue;
398 if (!strpos($chunk,
'[')) {
402 list($element, $attr) = explode(
'[', $chunk);
404 if ($element !==
'*') $elements[$element] =
true;
405 if (!$attr)
continue;
406 $attr = substr($attr, 0, strlen($attr) - 1);
407 $attr = explode(
'|', $attr);
408 foreach ($attr as $key) {
409 $attributes[
"$element.$key"] =
true;
413 return array($elements, $attributes);