国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
4.7KB

  1. <?php
  2. /**
  3. * Validates Color as defined by CSS.
  4. */
  5. class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
  6. {
  7. /**
  8. * @type HTMLPurifier_AttrDef_CSS_AlphaValue
  9. */
  10. protected $alpha;
  11. public function __construct()
  12. {
  13. $this->alpha = new HTMLPurifier_AttrDef_CSS_AlphaValue();
  14. }
  15. /**
  16. * @param string $color
  17. * @param HTMLPurifier_Config $config
  18. * @param HTMLPurifier_Context $context
  19. * @return bool|string
  20. */
  21. public function validate($color, $config, $context)
  22. {
  23. static $colors = null;
  24. if ($colors === null) {
  25. $colors = $config->get('Core.ColorKeywords');
  26. }
  27. $color = trim($color);
  28. if ($color === '') {
  29. return false;
  30. }
  31. $lower = strtolower($color);
  32. if (isset($colors[$lower])) {
  33. return $colors[$lower];
  34. }
  35. if (preg_match('#(rgb|rgba|hsl|hsla)\(#', $color, $matches) === 1) {
  36. $length = strlen($color);
  37. if (strpos($color, ')') !== $length - 1) {
  38. return false;
  39. }
  40. // get used function : rgb, rgba, hsl or hsla
  41. $function = $matches[1];
  42. $parameters_size = 3;
  43. $alpha_channel = false;
  44. if (substr($function, -1) === 'a') {
  45. $parameters_size = 4;
  46. $alpha_channel = true;
  47. }
  48. /*
  49. * Allowed types for values :
  50. * parameter_position => [type => max_value]
  51. */
  52. $allowed_types = array(
  53. 1 => array('percentage' => 100, 'integer' => 255),
  54. 2 => array('percentage' => 100, 'integer' => 255),
  55. 3 => array('percentage' => 100, 'integer' => 255),
  56. );
  57. $allow_different_types = false;
  58. if (strpos($function, 'hsl') !== false) {
  59. $allowed_types = array(
  60. 1 => array('integer' => 360),
  61. 2 => array('percentage' => 100),
  62. 3 => array('percentage' => 100),
  63. );
  64. $allow_different_types = true;
  65. }
  66. $values = trim(str_replace($function, '', $color), ' ()');
  67. $parts = explode(',', $values);
  68. if (count($parts) !== $parameters_size) {
  69. return false;
  70. }
  71. $type = false;
  72. $new_parts = array();
  73. $i = 0;
  74. foreach ($parts as $part) {
  75. $i++;
  76. $part = trim($part);
  77. if ($part === '') {
  78. return false;
  79. }
  80. // different check for alpha channel
  81. if ($alpha_channel === true && $i === count($parts)) {
  82. $result = $this->alpha->validate($part, $config, $context);
  83. if ($result === false) {
  84. return false;
  85. }
  86. $new_parts[] = (string)$result;
  87. continue;
  88. }
  89. if (substr($part, -1) === '%') {
  90. $current_type = 'percentage';
  91. } else {
  92. $current_type = 'integer';
  93. }
  94. if (!array_key_exists($current_type, $allowed_types[$i])) {
  95. return false;
  96. }
  97. if (!$type) {
  98. $type = $current_type;
  99. }
  100. if ($allow_different_types === false && $type != $current_type) {
  101. return false;
  102. }
  103. $max_value = $allowed_types[$i][$current_type];
  104. if ($current_type == 'integer') {
  105. // Return value between range 0 -> $max_value
  106. $new_parts[] = (int)max(min($part, $max_value), 0);
  107. } elseif ($current_type == 'percentage') {
  108. $new_parts[] = (float)max(min(rtrim($part, '%'), $max_value), 0) . '%';
  109. }
  110. }
  111. $new_values = implode(',', $new_parts);
  112. $color = $function . '(' . $new_values . ')';
  113. } else {
  114. // hexadecimal handling
  115. if ($color[0] === '#') {
  116. $hex = substr($color, 1);
  117. } else {
  118. $hex = $color;
  119. $color = '#' . $color;
  120. }
  121. $length = strlen($hex);
  122. if ($length !== 3 && $length !== 6) {
  123. return false;
  124. }
  125. if (!ctype_xdigit($hex)) {
  126. return false;
  127. }
  128. }
  129. return $color;
  130. }
  131. }
  132. // vim: et sw=4 sts=4