You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 line
3.3KB

  1. <?php
  2. /**
  3. * Definition that allows a set of elements, but disallows empty children.
  4. */
  5. class HTMLPurifier_ChildDef_Required extends HTMLPurifier_ChildDef
  6. {
  7. /**
  8. * Lookup table of allowed elements.
  9. * @type array
  10. */
  11. public $elements = array();
  12. /**
  13. * Whether or not the last passed node was all whitespace.
  14. * @type bool
  15. */
  16. protected $whitespace = false;
  17. /**
  18. * @param array|string $elements List of allowed element names (lowercase).
  19. */
  20. public function __construct($elements)
  21. {
  22. if (is_string($elements)) {
  23. $elements = str_replace(' ', '', $elements);
  24. $elements = explode('|', $elements);
  25. }
  26. $keys = array_keys($elements);
  27. if ($keys == array_keys($keys)) {
  28. $elements = array_flip($elements);
  29. foreach ($elements as $i => $x) {
  30. $elements[$i] = true;
  31. if (empty($i)) {
  32. unset($elements[$i]);
  33. } // remove blank
  34. }
  35. }
  36. $this->elements = $elements;
  37. }
  38. /**
  39. * @type bool
  40. */
  41. public $allow_empty = false;
  42. /**
  43. * @type string
  44. */
  45. public $type = 'required';
  46. /**
  47. * @param array $children
  48. * @param HTMLPurifier_Config $config
  49. * @param HTMLPurifier_Context $context
  50. * @return array
  51. */
  52. public function validateChildren($children, $config, $context)
  53. {
  54. // Flag for subclasses
  55. $this->whitespace = false;
  56. // if there are no tokens, delete parent node
  57. if (empty($children)) {
  58. return false;
  59. }
  60. // the new set of children
  61. $result = array();
  62. // whether or not parsed character data is allowed
  63. // this controls whether or not we silently drop a tag
  64. // or generate escaped HTML from it
  65. $pcdata_allowed = isset($this->elements['#PCDATA']);
  66. // a little sanity check to make sure it's not ALL whitespace
  67. $all_whitespace = true;
  68. $stack = array_reverse($children);
  69. while (!empty($stack)) {
  70. $node = array_pop($stack);
  71. if (!empty($node->is_whitespace)) {
  72. $result[] = $node;
  73. continue;
  74. }
  75. $all_whitespace = false; // phew, we're not talking about whitespace
  76. if (!isset($this->elements[$node->name])) {
  77. // special case text
  78. // XXX One of these ought to be redundant or something
  79. if ($pcdata_allowed && $node instanceof HTMLPurifier_Node_Text) {
  80. $result[] = $node;
  81. continue;
  82. }
  83. // spill the child contents in
  84. // ToDo: Make configurable
  85. if ($node instanceof HTMLPurifier_Node_Element) {
  86. for ($i = count($node->children) - 1; $i >= 0; $i--) {
  87. $stack[] = $node->children[$i];
  88. }
  89. continue;
  90. }
  91. continue;
  92. }
  93. $result[] = $node;
  94. }
  95. if (empty($result)) {
  96. return false;
  97. }
  98. if ($all_whitespace) {
  99. $this->whitespace = true;
  100. return false;
  101. }
  102. return $result;
  103. }
  104. }
  105. // vim: et sw=4 sts=4