Whoops, forgot to edit WHATSNEW
[htmlpurifier.git] / library / HTMLPurifier / AttrDef / CSS / Font.php
blob579b97ef1ca60344af77774e14beb7dc612384aa
1 <?php
3 /**
4 * Validates shorthand CSS property font.
5 */
6 class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
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.
17 protected $info = array();
19 /**
20 * @param HTMLPurifier_Config $config
22 public function __construct($config)
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'];
33 /**
34 * @param string $string
35 * @param HTMLPurifier_Config $config
36 * @param HTMLPurifier_Context $context
37 * @return bool|string
39 public function validate($string, $config, $context)
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
50 // regular pre-processing
51 $string = $this->parseCDATA($string);
52 if ($string === '') {
53 return false;
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;
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
68 for ($i = 0, $size = count($bits); $i < $size; $i++) {
69 if ($bits[$i] === '') {
70 continue;
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;
78 $r = $this->info[$validator_name]->validate(
79 $bits[$i],
80 $config,
81 $context
83 if ($r !== false) {
84 $final .= $r . ' ';
85 $caught[$validator_name] = true;
86 break;
89 // all three caught, continue on
90 if (count($caught) >= 3) {
91 $stage = 1;
93 if ($r !== false) {
94 break;
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;
106 } else {
107 $font_size = $bits[$i];
108 $line_height = false;
110 $r = $this->info['font-size']->validate(
111 $font_size,
112 $config,
113 $context
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;
124 if ($bits[$j] === '/') {
125 if ($found_slash) {
126 return false;
127 } else {
128 $found_slash = true;
129 continue;
132 $line_height = $bits[$j];
133 break;
135 } else {
136 // slash already found
137 $found_slash = true;
138 $j = $i;
140 if ($found_slash) {
141 $i = $j;
142 $r = $this->info['line-height']->validate(
143 $line_height,
144 $config,
145 $context
147 if ($r !== false) {
148 $final .= '/' . $r;
151 $final .= ' ';
152 $stage = 2;
153 break;
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
164 if ($r !== false) {
165 $final .= $r . ' ';
166 // processing completed successfully
167 return rtrim($final);
169 return false;
172 return false;
176 // vim: et sw=4 sts=4