Search moodle.org's
Developer Documentation

See Release Notes

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