177 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			PHP
		
	
	
		
		
			
		
	
	
			177 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			PHP
		
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Validates shorthand CSS property font.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Local copy of validators
							 | 
						||
| 
								 | 
							
								     * @type HTMLPurifier_AttrDef[]
							 | 
						||
| 
								 | 
							
								     * @note If we moved specific CSS property definitions to their own
							 | 
						||
| 
								 | 
							
								     *       classes instead of having them be assembled at run time by
							 | 
						||
| 
								 | 
							
								     *       CSSDefinition, this wouldn't be necessary.  We'd instantiate
							 | 
						||
| 
								 | 
							
								     *       our own copies.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected $info = array();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @param HTMLPurifier_Config $config
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function __construct($config)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $def = $config->getCSSDefinition();
							 | 
						||
| 
								 | 
							
								        $this->info['font-style'] = $def->info['font-style'];
							 | 
						||
| 
								 | 
							
								        $this->info['font-variant'] = $def->info['font-variant'];
							 | 
						||
| 
								 | 
							
								        $this->info['font-weight'] = $def->info['font-weight'];
							 | 
						||
| 
								 | 
							
								        $this->info['font-size'] = $def->info['font-size'];
							 | 
						||
| 
								 | 
							
								        $this->info['line-height'] = $def->info['line-height'];
							 | 
						||
| 
								 | 
							
								        $this->info['font-family'] = $def->info['font-family'];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @param string $string
							 | 
						||
| 
								 | 
							
								     * @param HTMLPurifier_Config $config
							 | 
						||
| 
								 | 
							
								     * @param HTMLPurifier_Context $context
							 | 
						||
| 
								 | 
							
								     * @return bool|string
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function validate($string, $config, $context)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        static $system_fonts = array(
							 | 
						||
| 
								 | 
							
								            'caption' => true,
							 | 
						||
| 
								 | 
							
								            'icon' => true,
							 | 
						||
| 
								 | 
							
								            'menu' => true,
							 | 
						||
| 
								 | 
							
								            'message-box' => true,
							 | 
						||
| 
								 | 
							
								            'small-caption' => true,
							 | 
						||
| 
								 | 
							
								            'status-bar' => true
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // regular pre-processing
							 | 
						||
| 
								 | 
							
								        $string = $this->parseCDATA($string);
							 | 
						||
| 
								 | 
							
								        if ($string === '') {
							 | 
						||
| 
								 | 
							
								            return false;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // check if it's one of the keywords
							 | 
						||
| 
								 | 
							
								        $lowercase_string = strtolower($string);
							 | 
						||
| 
								 | 
							
								        if (isset($system_fonts[$lowercase_string])) {
							 | 
						||
| 
								 | 
							
								            return $lowercase_string;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $bits = explode(' ', $string); // bits to process
							 | 
						||
| 
								 | 
							
								        $stage = 0; // this indicates what we're looking for
							 | 
						||
| 
								 | 
							
								        $caught = array(); // which stage 0 properties have we caught?
							 | 
						||
| 
								 | 
							
								        $stage_1 = array('font-style', 'font-variant', 'font-weight');
							 | 
						||
| 
								 | 
							
								        $final = ''; // output
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for ($i = 0, $size = count($bits); $i < $size; $i++) {
							 | 
						||
| 
								 | 
							
								            if ($bits[$i] === '') {
							 | 
						||
| 
								 | 
							
								                continue;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            switch ($stage) {
							 | 
						||
| 
								 | 
							
								                case 0: // attempting to catch font-style, font-variant or font-weight
							 | 
						||
| 
								 | 
							
								                    foreach ($stage_1 as $validator_name) {
							 | 
						||
| 
								 | 
							
								                        if (isset($caught[$validator_name])) {
							 | 
						||
| 
								 | 
							
								                            continue;
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        $r = $this->info[$validator_name]->validate(
							 | 
						||
| 
								 | 
							
								                            $bits[$i],
							 | 
						||
| 
								 | 
							
								                            $config,
							 | 
						||
| 
								 | 
							
								                            $context
							 | 
						||
| 
								 | 
							
								                        );
							 | 
						||
| 
								 | 
							
								                        if ($r !== false) {
							 | 
						||
| 
								 | 
							
								                            $final .= $r . ' ';
							 | 
						||
| 
								 | 
							
								                            $caught[$validator_name] = true;
							 | 
						||
| 
								 | 
							
								                            break;
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    // all three caught, continue on
							 | 
						||
| 
								 | 
							
								                    if (count($caught) >= 3) {
							 | 
						||
| 
								 | 
							
								                        $stage = 1;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    if ($r !== false) {
							 | 
						||
| 
								 | 
							
								                        break;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                case 1: // attempting to catch font-size and perhaps line-height
							 | 
						||
| 
								 | 
							
								                    $found_slash = false;
							 | 
						||
| 
								 | 
							
								                    if (strpos($bits[$i], '/') !== false) {
							 | 
						||
| 
								 | 
							
								                        list($font_size, $line_height) =
							 | 
						||
| 
								 | 
							
								                            explode('/', $bits[$i]);
							 | 
						||
| 
								 | 
							
								                        if ($line_height === '') {
							 | 
						||
| 
								 | 
							
								                            // ooh, there's a space after the slash!
							 | 
						||
| 
								 | 
							
								                            $line_height = false;
							 | 
						||
| 
								 | 
							
								                            $found_slash = true;
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                    } else {
							 | 
						||
| 
								 | 
							
								                        $font_size = $bits[$i];
							 | 
						||
| 
								 | 
							
								                        $line_height = false;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    $r = $this->info['font-size']->validate(
							 | 
						||
| 
								 | 
							
								                        $font_size,
							 | 
						||
| 
								 | 
							
								                        $config,
							 | 
						||
| 
								 | 
							
								                        $context
							 | 
						||
| 
								 | 
							
								                    );
							 | 
						||
| 
								 | 
							
								                    if ($r !== false) {
							 | 
						||
| 
								 | 
							
								                        $final .= $r;
							 | 
						||
| 
								 | 
							
								                        // attempt to catch line-height
							 | 
						||
| 
								 | 
							
								                        if ($line_height === false) {
							 | 
						||
| 
								 | 
							
								                            // we need to scroll forward
							 | 
						||
| 
								 | 
							
								                            for ($j = $i + 1; $j < $size; $j++) {
							 | 
						||
| 
								 | 
							
								                                if ($bits[$j] === '') {
							 | 
						||
| 
								 | 
							
								                                    continue;
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                                if ($bits[$j] === '/') {
							 | 
						||
| 
								 | 
							
								                                    if ($found_slash) {
							 | 
						||
| 
								 | 
							
								                                        return false;
							 | 
						||
| 
								 | 
							
								                                    } else {
							 | 
						||
| 
								 | 
							
								                                        $found_slash = true;
							 | 
						||
| 
								 | 
							
								                                        continue;
							 | 
						||
| 
								 | 
							
								                                    }
							 | 
						||
| 
								 | 
							
								                                }
							 | 
						||
| 
								 | 
							
								                                $line_height = $bits[$j];
							 | 
						||
| 
								 | 
							
								                                break;
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                        } else {
							 | 
						||
| 
								 | 
							
								                            // slash already found
							 | 
						||
| 
								 | 
							
								                            $found_slash = true;
							 | 
						||
| 
								 | 
							
								                            $j = $i;
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        if ($found_slash) {
							 | 
						||
| 
								 | 
							
								                            $i = $j;
							 | 
						||
| 
								 | 
							
								                            $r = $this->info['line-height']->validate(
							 | 
						||
| 
								 | 
							
								                                $line_height,
							 | 
						||
| 
								 | 
							
								                                $config,
							 | 
						||
| 
								 | 
							
								                                $context
							 | 
						||
| 
								 | 
							
								                            );
							 | 
						||
| 
								 | 
							
								                            if ($r !== false) {
							 | 
						||
| 
								 | 
							
								                                $final .= '/' . $r;
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        $final .= ' ';
							 | 
						||
| 
								 | 
							
								                        $stage = 2;
							 | 
						||
| 
								 | 
							
								                        break;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    return false;
							 | 
						||
| 
								 | 
							
								                case 2: // attempting to catch font-family
							 | 
						||
| 
								 | 
							
								                    $font_family =
							 | 
						||
| 
								 | 
							
								                        implode(' ', array_slice($bits, $i, $size - $i));
							 | 
						||
| 
								 | 
							
								                    $r = $this->info['font-family']->validate(
							 | 
						||
| 
								 | 
							
								                        $font_family,
							 | 
						||
| 
								 | 
							
								                        $config,
							 | 
						||
| 
								 | 
							
								                        $context
							 | 
						||
| 
								 | 
							
								                    );
							 | 
						||
| 
								 | 
							
								                    if ($r !== false) {
							 | 
						||
| 
								 | 
							
								                        $final .= $r . ' ';
							 | 
						||
| 
								 | 
							
								                        // processing completed successfully
							 | 
						||
| 
								 | 
							
								                        return rtrim($final);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    return false;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// vim: et sw=4 sts=4
							 |