Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 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   * Validates shorthand CSS property font.

   5   */
   6  class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
   7  {
   8  
   9      /**

  10       * Local copy of validators

  11       * @type HTMLPurifier_AttrDef[]

  12       * @note If we moved specific CSS property definitions to their own

  13       *       classes instead of having them be assembled at run time by

  14       *       CSSDefinition, this wouldn't be necessary.  We'd instantiate

  15       *       our own copies.

  16       */
  17      protected $info = array();
  18  
  19      /**

  20       * @param HTMLPurifier_Config $config

  21       */
  22      public function __construct($config)
  23      {
  24          $def = $config->getCSSDefinition();
  25          $this->info['font-style'] = $def->info['font-style'];
  26          $this->info['font-variant'] = $def->info['font-variant'];
  27          $this->info['font-weight'] = $def->info['font-weight'];
  28          $this->info['font-size'] = $def->info['font-size'];
  29          $this->info['line-height'] = $def->info['line-height'];
  30          $this->info['font-family'] = $def->info['font-family'];
  31      }
  32  
  33      /**

  34       * @param string $string

  35       * @param HTMLPurifier_Config $config

  36       * @param HTMLPurifier_Context $context

  37       * @return bool|string

  38       */
  39      public function validate($string, $config, $context)
  40      {
  41          static $system_fonts = array(
  42              'caption' => true,
  43              'icon' => true,
  44              'menu' => true,
  45              'message-box' => true,
  46              'small-caption' => true,
  47              'status-bar' => true
  48          );
  49  
  50          // regular pre-processing

  51          $string = $this->parseCDATA($string);
  52          if ($string === '') {
  53              return false;
  54          }
  55  
  56          // check if it's one of the keywords

  57          $lowercase_string = strtolower($string);
  58          if (isset($system_fonts[$lowercase_string])) {
  59              return $lowercase_string;
  60          }
  61  
  62          $bits = explode(' ', $string); // bits to process

  63          $stage = 0; // this indicates what we're looking for

  64          $caught = array(); // which stage 0 properties have we caught?

  65          $stage_1 = array('font-style', 'font-variant', 'font-weight');
  66          $final = ''; // output

  67  
  68          for ($i = 0, $size = count($bits); $i < $size; $i++) {
  69              if ($bits[$i] === '') {
  70                  continue;
  71              }
  72              switch ($stage) {
  73                  case 0: // attempting to catch font-style, font-variant or font-weight
  74                      foreach ($stage_1 as $validator_name) {
  75                          if (isset($caught[$validator_name])) {
  76                              continue;
  77                          }
  78                          $r = $this->info[$validator_name]->validate(
  79                              $bits[$i],
  80                              $config,
  81                              $context
  82                          );
  83                          if ($r !== false) {
  84                              $final .= $r . ' ';
  85                              $caught[$validator_name] = true;
  86                              break;
  87                          }
  88                      }
  89                      // all three caught, continue on

  90                      if (count($caught) >= 3) {
  91                          $stage = 1;
  92                      }
  93                      if ($r !== false) {
  94                          break;
  95                      }
  96                  case 1: // attempting to catch font-size and perhaps line-height
  97                      $found_slash = false;
  98                      if (strpos($bits[$i], '/') !== false) {
  99                          list($font_size, $line_height) =
 100                              explode('/', $bits[$i]);
 101                          if ($line_height === '') {
 102                              // ooh, there's a space after the slash!

 103                              $line_height = false;
 104                              $found_slash = true;
 105                          }
 106                      } else {
 107                          $font_size = $bits[$i];
 108                          $line_height = false;
 109                      }
 110                      $r = $this->info['font-size']->validate(
 111                          $font_size,
 112                          $config,
 113                          $context
 114                      );
 115                      if ($r !== false) {
 116                          $final .= $r;
 117                          // attempt to catch line-height

 118                          if ($line_height === false) {
 119                              // we need to scroll forward

 120                              for ($j = $i + 1; $j < $size; $j++) {
 121                                  if ($bits[$j] === '') {
 122                                      continue;
 123                                  }
 124                                  if ($bits[$j] === '/') {
 125                                      if ($found_slash) {
 126                                          return false;
 127                                      } else {
 128                                          $found_slash = true;
 129                                          continue;
 130                                      }
 131                                  }
 132                                  $line_height = $bits[$j];
 133                                  break;
 134                              }
 135                          } else {
 136                              // slash already found

 137                              $found_slash = true;
 138                              $j = $i;
 139                          }
 140                          if ($found_slash) {
 141                              $i = $j;
 142                              $r = $this->info['line-height']->validate(
 143                                  $line_height,
 144                                  $config,
 145                                  $context
 146                              );
 147                              if ($r !== false) {
 148                                  $final .= '/' . $r;
 149                              }
 150                          }
 151                          $final .= ' ';
 152                          $stage = 2;
 153                          break;
 154                      }
 155                      return false;
 156                  case 2: // attempting to catch font-family
 157                      $font_family =
 158                          implode(' ', array_slice($bits, $i, $size - $i));
 159                      $r = $this->info['font-family']->validate(
 160                          $font_family,
 161                          $config,
 162                          $context
 163                      );
 164                      if ($r !== false) {
 165                          $final .= $r . ' ';
 166                          // processing completed successfully

 167                          return rtrim($final);
 168                      }
 169                      return false;
 170              }
 171          }
 172          return false;
 173      }
 174  }
 175  
 176  // vim: et sw=4 sts=4