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.

SafeObject.php 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <?php
  2. /**
  3. * Adds important param elements to inside of object in order to make
  4. * things safe.
  5. */
  6. class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector
  7. {
  8. /**
  9. * @type string
  10. */
  11. public $name = 'SafeObject';
  12. /**
  13. * @type array
  14. */
  15. public $needed = array('object', 'param');
  16. /**
  17. * @type array
  18. */
  19. protected $objectStack = array();
  20. /**
  21. * @type array
  22. */
  23. protected $paramStack = array();
  24. /**
  25. * Keep this synchronized with AttrTransform/SafeParam.php.
  26. * @type array
  27. */
  28. protected $addParam = array(
  29. 'allowScriptAccess' => 'never',
  30. 'allowNetworking' => 'internal',
  31. );
  32. /**
  33. * @type array
  34. */
  35. protected $allowedParam = array(
  36. 'wmode' => true,
  37. 'movie' => true,
  38. 'flashvars' => true,
  39. 'src' => true,
  40. 'allowFullScreen' => true, // if omitted, assume to be 'false'
  41. );
  42. /**
  43. * @param HTMLPurifier_Config $config
  44. * @param HTMLPurifier_Context $context
  45. * @return void
  46. */
  47. public function prepare($config, $context)
  48. {
  49. parent::prepare($config, $context);
  50. }
  51. /**
  52. * @param HTMLPurifier_Token $token
  53. */
  54. public function handleElement(&$token)
  55. {
  56. if ($token->name == 'object') {
  57. $this->objectStack[] = $token;
  58. $this->paramStack[] = array();
  59. $new = array($token);
  60. foreach ($this->addParam as $name => $value) {
  61. $new[] = new HTMLPurifier_Token_Empty('param', array('name' => $name, 'value' => $value));
  62. }
  63. $token = $new;
  64. } elseif ($token->name == 'param') {
  65. $nest = count($this->currentNesting) - 1;
  66. if ($nest >= 0 && $this->currentNesting[$nest]->name === 'object') {
  67. $i = count($this->objectStack) - 1;
  68. if (!isset($token->attr['name'])) {
  69. $token = false;
  70. return;
  71. }
  72. $n = $token->attr['name'];
  73. // We need this fix because YouTube doesn't supply a data
  74. // attribute, which we need if a type is specified. This is
  75. // *very* Flash specific.
  76. if (!isset($this->objectStack[$i]->attr['data']) &&
  77. ($token->attr['name'] == 'movie' || $token->attr['name'] == 'src')
  78. ) {
  79. $this->objectStack[$i]->attr['data'] = $token->attr['value'];
  80. }
  81. // Check if the parameter is the correct value but has not
  82. // already been added
  83. if (!isset($this->paramStack[$i][$n]) &&
  84. isset($this->addParam[$n]) &&
  85. $token->attr['name'] === $this->addParam[$n]) {
  86. // keep token, and add to param stack
  87. $this->paramStack[$i][$n] = true;
  88. } elseif (isset($this->allowedParam[$n])) {
  89. // keep token, don't do anything to it
  90. // (could possibly check for duplicates here)
  91. } else {
  92. $token = false;
  93. }
  94. } else {
  95. // not directly inside an object, DENY!
  96. $token = false;
  97. }
  98. }
  99. }
  100. public function handleEnd(&$token)
  101. {
  102. // This is the WRONG way of handling the object and param stacks;
  103. // we should be inserting them directly on the relevant object tokens
  104. // so that the global stack handling handles it.
  105. if ($token->name == 'object') {
  106. array_pop($this->objectStack);
  107. array_pop($this->paramStack);
  108. }
  109. }
  110. }
  111. // vim: et sw=4 sts=4