HTMLPurifier 4.4.0
|
00001 <?php 00002 00006 class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef 00007 { 00008 00017 protected $info = array(); 00018 00019 public function __construct($config) { 00020 $def = $config->getCSSDefinition(); 00021 $this->info['font-style'] = $def->info['font-style']; 00022 $this->info['font-variant'] = $def->info['font-variant']; 00023 $this->info['font-weight'] = $def->info['font-weight']; 00024 $this->info['font-size'] = $def->info['font-size']; 00025 $this->info['line-height'] = $def->info['line-height']; 00026 $this->info['font-family'] = $def->info['font-family']; 00027 } 00028 00029 public function validate($string, $config, $context) { 00030 00031 static $system_fonts = array( 00032 'caption' => true, 00033 'icon' => true, 00034 'menu' => true, 00035 'message-box' => true, 00036 'small-caption' => true, 00037 'status-bar' => true 00038 ); 00039 00040 // regular pre-processing 00041 $string = $this->parseCDATA($string); 00042 if ($string === '') return false; 00043 00044 // check if it's one of the keywords 00045 $lowercase_string = strtolower($string); 00046 if (isset($system_fonts[$lowercase_string])) { 00047 return $lowercase_string; 00048 } 00049 00050 $bits = explode(' ', $string); // bits to process 00051 $stage = 0; // this indicates what we're looking for 00052 $caught = array(); // which stage 0 properties have we caught? 00053 $stage_1 = array('font-style', 'font-variant', 'font-weight'); 00054 $final = ''; // output 00055 00056 for ($i = 0, $size = count($bits); $i < $size; $i++) { 00057 if ($bits[$i] === '') continue; 00058 switch ($stage) { 00059 00060 // attempting to catch font-style, font-variant or font-weight 00061 case 0: 00062 foreach ($stage_1 as $validator_name) { 00063 if (isset($caught[$validator_name])) continue; 00064 $r = $this->info[$validator_name]->validate( 00065 $bits[$i], $config, $context); 00066 if ($r !== false) { 00067 $final .= $r . ' '; 00068 $caught[$validator_name] = true; 00069 break; 00070 } 00071 } 00072 // all three caught, continue on 00073 if (count($caught) >= 3) $stage = 1; 00074 if ($r !== false) break; 00075 00076 // attempting to catch font-size and perhaps line-height 00077 case 1: 00078 $found_slash = false; 00079 if (strpos($bits[$i], '/') !== false) { 00080 list($font_size, $line_height) = 00081 explode('/', $bits[$i]); 00082 if ($line_height === '') { 00083 // ooh, there's a space after the slash! 00084 $line_height = false; 00085 $found_slash = true; 00086 } 00087 } else { 00088 $font_size = $bits[$i]; 00089 $line_height = false; 00090 } 00091 $r = $this->info['font-size']->validate( 00092 $font_size, $config, $context); 00093 if ($r !== false) { 00094 $final .= $r; 00095 // attempt to catch line-height 00096 if ($line_height === false) { 00097 // we need to scroll forward 00098 for ($j = $i + 1; $j < $size; $j++) { 00099 if ($bits[$j] === '') continue; 00100 if ($bits[$j] === '/') { 00101 if ($found_slash) { 00102 return false; 00103 } else { 00104 $found_slash = true; 00105 continue; 00106 } 00107 } 00108 $line_height = $bits[$j]; 00109 break; 00110 } 00111 } else { 00112 // slash already found 00113 $found_slash = true; 00114 $j = $i; 00115 } 00116 if ($found_slash) { 00117 $i = $j; 00118 $r = $this->info['line-height']->validate( 00119 $line_height, $config, $context); 00120 if ($r !== false) { 00121 $final .= '/' . $r; 00122 } 00123 } 00124 $final .= ' '; 00125 $stage = 2; 00126 break; 00127 } 00128 return false; 00129 00130 // attempting to catch font-family 00131 case 2: 00132 $font_family = 00133 implode(' ', array_slice($bits, $i, $size - $i)); 00134 $r = $this->info['font-family']->validate( 00135 $font_family, $config, $context); 00136 if ($r !== false) { 00137 $final .= $r . ' '; 00138 // processing completed successfully 00139 return rtrim($final); 00140 } 00141 return false; 00142 } 00143 } 00144 return false; 00145 } 00146 00147 } 00148 00149 // vim: et sw=4 sts=4