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.

103 lines
2.7KB

  1. <?php
  2. /**
  3. * Custom validation class, accepts DTD child definitions
  4. *
  5. * @warning Currently this class is an all or nothing proposition, that is,
  6. * it will only give a bool return value.
  7. */
  8. class HTMLPurifier_ChildDef_Custom extends HTMLPurifier_ChildDef
  9. {
  10. /**
  11. * @type string
  12. */
  13. public $type = 'custom';
  14. /**
  15. * @type bool
  16. */
  17. public $allow_empty = false;
  18. /**
  19. * Allowed child pattern as defined by the DTD.
  20. * @type string
  21. */
  22. public $dtd_regex;
  23. /**
  24. * PCRE regex derived from $dtd_regex.
  25. * @type string
  26. */
  27. private $_pcre_regex;
  28. /**
  29. * @param $dtd_regex Allowed child pattern from the DTD
  30. */
  31. public function __construct($dtd_regex)
  32. {
  33. $this->dtd_regex = $dtd_regex;
  34. $this->_compileRegex();
  35. }
  36. /**
  37. * Compiles the PCRE regex from a DTD regex ($dtd_regex to $_pcre_regex)
  38. */
  39. protected function _compileRegex()
  40. {
  41. $raw = str_replace(' ', '', $this->dtd_regex);
  42. if ($raw{0} != '(') {
  43. $raw = "($raw)";
  44. }
  45. $el = '[#a-zA-Z0-9_.-]+';
  46. $reg = $raw;
  47. // COMPLICATED! AND MIGHT BE BUGGY! I HAVE NO CLUE WHAT I'M
  48. // DOING! Seriously: if there's problems, please report them.
  49. // collect all elements into the $elements array
  50. preg_match_all("/$el/", $reg, $matches);
  51. foreach ($matches[0] as $match) {
  52. $this->elements[$match] = true;
  53. }
  54. // setup all elements as parentheticals with leading commas
  55. $reg = preg_replace("/$el/", '(,\\0)', $reg);
  56. // remove commas when they were not solicited
  57. $reg = preg_replace("/([^,(|]\(+),/", '\\1', $reg);
  58. // remove all non-paranthetical commas: they are handled by first regex
  59. $reg = preg_replace("/,\(/", '(', $reg);
  60. $this->_pcre_regex = $reg;
  61. }
  62. /**
  63. * @param HTMLPurifier_Node[] $children
  64. * @param HTMLPurifier_Config $config
  65. * @param HTMLPurifier_Context $context
  66. * @return bool
  67. */
  68. public function validateChildren($children, $config, $context)
  69. {
  70. $list_of_children = '';
  71. $nesting = 0; // depth into the nest
  72. foreach ($children as $node) {
  73. if (!empty($node->is_whitespace)) {
  74. continue;
  75. }
  76. $list_of_children .= $node->name . ',';
  77. }
  78. // add leading comma to deal with stray comma declarations
  79. $list_of_children = ',' . rtrim($list_of_children, ',');
  80. $okay =
  81. preg_match(
  82. '/^,?' . $this->_pcre_regex . '$/',
  83. $list_of_children
  84. );
  85. return (bool)$okay;
  86. }
  87. }
  88. // vim: et sw=4 sts=4