Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are 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