File indexing completed on 2025-02-02 05:43:43
0001 <?php 0002 0003 /** 0004 * Adds important param elements to inside of object in order to make 0005 * things safe. 0006 */ 0007 class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector 0008 { 0009 /** 0010 * @type string 0011 */ 0012 public $name = 'SafeObject'; 0013 0014 /** 0015 * @type array 0016 */ 0017 public $needed = array('object', 'param'); 0018 0019 /** 0020 * @type array 0021 */ 0022 protected $objectStack = array(); 0023 0024 /** 0025 * @type array 0026 */ 0027 protected $paramStack = array(); 0028 0029 /** 0030 * Keep this synchronized with AttrTransform/SafeParam.php. 0031 * @type array 0032 */ 0033 protected $addParam = array( 0034 'allowScriptAccess' => 'never', 0035 'allowNetworking' => 'internal', 0036 ); 0037 0038 /** 0039 * These are all lower-case keys. 0040 * @type array 0041 */ 0042 protected $allowedParam = array( 0043 'wmode' => true, 0044 'movie' => true, 0045 'flashvars' => true, 0046 'src' => true, 0047 'allowfullscreen' => true, // if omitted, assume to be 'false' 0048 ); 0049 0050 /** 0051 * @param HTMLPurifier_Config $config 0052 * @param HTMLPurifier_Context $context 0053 * @return void 0054 */ 0055 public function prepare($config, $context) 0056 { 0057 parent::prepare($config, $context); 0058 } 0059 0060 /** 0061 * @param HTMLPurifier_Token $token 0062 */ 0063 public function handleElement(&$token) 0064 { 0065 if ($token->name == 'object') { 0066 $this->objectStack[] = $token; 0067 $this->paramStack[] = array(); 0068 $new = array($token); 0069 foreach ($this->addParam as $name => $value) { 0070 $new[] = new HTMLPurifier_Token_Empty('param', array('name' => $name, 'value' => $value)); 0071 } 0072 $token = $new; 0073 } elseif ($token->name == 'param') { 0074 $nest = count($this->currentNesting) - 1; 0075 if ($nest >= 0 && $this->currentNesting[$nest]->name === 'object') { 0076 $i = count($this->objectStack) - 1; 0077 if (!isset($token->attr['name'])) { 0078 $token = false; 0079 return; 0080 } 0081 $n = $token->attr['name']; 0082 // We need this fix because YouTube doesn't supply a data 0083 // attribute, which we need if a type is specified. This is 0084 // *very* Flash specific. 0085 if (!isset($this->objectStack[$i]->attr['data']) && 0086 ($token->attr['name'] == 'movie' || $token->attr['name'] == 'src') 0087 ) { 0088 $this->objectStack[$i]->attr['data'] = $token->attr['value']; 0089 } 0090 // Check if the parameter is the correct value but has not 0091 // already been added 0092 if (!isset($this->paramStack[$i][$n]) && 0093 isset($this->addParam[$n]) && 0094 $token->attr['name'] === $this->addParam[$n]) { 0095 // keep token, and add to param stack 0096 $this->paramStack[$i][$n] = true; 0097 } elseif (isset($this->allowedParam[strtolower($n)])) { 0098 // keep token, don't do anything to it 0099 // (could possibly check for duplicates here) 0100 // Note: In principle, parameters should be case sensitive. 0101 // But it seems they are not really; so accept any case. 0102 } else { 0103 $token = false; 0104 } 0105 } else { 0106 // not directly inside an object, DENY! 0107 $token = false; 0108 } 0109 } 0110 } 0111 0112 public function handleEnd(&$token) 0113 { 0114 // This is the WRONG way of handling the object and param stacks; 0115 // we should be inserting them directly on the relevant object tokens 0116 // so that the global stack handling handles it. 0117 if ($token->name == 'object') { 0118 array_pop($this->objectStack); 0119 array_pop($this->paramStack); 0120 } 0121 } 0122 } 0123 0124 // vim: et sw=4 sts=4