Custom.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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. public $type = 'custom';
  11. public $allow_empty = false;
  12. /**
  13. * Allowed child pattern as defined by the DTD
  14. */
  15. public $dtd_regex;
  16. /**
  17. * PCRE regex derived from $dtd_regex
  18. * @private
  19. */
  20. private $_pcre_regex;
  21. /**
  22. * @param $dtd_regex Allowed child pattern from the DTD
  23. */
  24. public function __construct($dtd_regex) {
  25. $this->dtd_regex = $dtd_regex;
  26. $this->_compileRegex();
  27. }
  28. /**
  29. * Compiles the PCRE regex from a DTD regex ($dtd_regex to $_pcre_regex)
  30. */
  31. protected function _compileRegex() {
  32. $raw = str_replace(' ', '', $this->dtd_regex);
  33. if ($raw{0} != '(') {
  34. $raw = "($raw)";
  35. }
  36. $el = '[#a-zA-Z0-9_.-]+';
  37. $reg = $raw;
  38. // COMPLICATED! AND MIGHT BE BUGGY! I HAVE NO CLUE WHAT I'M
  39. // DOING! Seriously: if there's problems, please report them.
  40. // collect all elements into the $elements array
  41. preg_match_all("/$el/", $reg, $matches);
  42. foreach ($matches[0] as $match) {
  43. $this->elements[$match] = true;
  44. }
  45. // setup all elements as parentheticals with leading commas
  46. $reg = preg_replace("/$el/", '(,\\0)', $reg);
  47. // remove commas when they were not solicited
  48. $reg = preg_replace("/([^,(|]\(+),/", '\\1', $reg);
  49. // remove all non-paranthetical commas: they are handled by first regex
  50. $reg = preg_replace("/,\(/", '(', $reg);
  51. $this->_pcre_regex = $reg;
  52. }
  53. public function validateChildren($tokens_of_children, $config, $context) {
  54. $list_of_children = '';
  55. $nesting = 0; // depth into the nest
  56. foreach ($tokens_of_children as $token) {
  57. if (!empty($token->is_whitespace)) continue;
  58. $is_child = ($nesting == 0); // direct
  59. if ($token instanceof HTMLPurifier_Token_Start) {
  60. $nesting++;
  61. } elseif ($token instanceof HTMLPurifier_Token_End) {
  62. $nesting--;
  63. }
  64. if ($is_child) {
  65. $list_of_children .= $token->name . ',';
  66. }
  67. }
  68. // add leading comma to deal with stray comma declarations
  69. $list_of_children = ',' . rtrim($list_of_children, ',');
  70. $okay =
  71. preg_match(
  72. '/^,?'.$this->_pcre_regex.'$/',
  73. $list_of_children
  74. );
  75. return (bool) $okay;
  76. }
  77. }
  78. // vim: et sw=4 sts=4