Skip to content

Instantly share code, notes, and snippets.

@georgestephanis
Last active January 20, 2023 18:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save georgestephanis/a998bb9495739023353d to your computer and use it in GitHub Desktop.
Save georgestephanis/a998bb9495739023353d to your computer and use it in GitHub Desktop.
<?php
/**
* Function to sanitize CSS color inputs to ensure we're not using out anything dangerous.
*
* This function can sanitize Named Colors, Hex Colors, RGB, RGBA, HSL, and HSLA.
*
* @param string $color The color to sanitize.
*
* @return string|null Null if it failed sanitization, the printable string if it passed.
*/
function sanitize_css_color( $color ){
if ( empty( $color ) ) {
return '';
}
// If there's a semicolon in it,
if ( false !== strpos( $color, ';' ) ) {
$color_chunks = explode( ';', $color, 2 );
$color = $color_chunks[0];
}
// Trim it.
$color = trim( $color );
// named colors, taken from https://drafts.csswg.org/css-color/ (includes rebeccapurple)
$named_colors = apply_filters( 'css_named_colors', array(
'aliceblue',
'antiquewhite',
'aqua',
'aquamarine',
'azure',
'beige',
'bisque',
'black',
'blanchedalmond',
'blue',
'blueviolet',
'brown',
'burlywood',
'cadetblue',
'chartreuse',
'chocolate',
'coral',
'cornflowerblue',
'cornsilk',
'crimson',
'cyan',
'darkblue',
'darkcyan',
'darkgoldenrod',
'darkgray',
'darkgreen',
'darkgrey',
'darkkhaki',
'darkmagenta',
'darkolivegreen',
'darkorange',
'darkorchid',
'darkred',
'darksalmon',
'darkseagreen',
'darkslateblue',
'darkslategray',
'darkslategrey',
'darkturquoise',
'darkviolet',
'deeppink',
'deepskyblue',
'dimgray',
'dimgrey',
'dodgerblue',
'firebrick',
'floralwhite',
'forestgreen',
'fuchsia',
'gainsboro',
'ghostwhite',
'gold',
'goldenrod',
'gray',
'green',
'greenyellow',
'grey',
'honeydew',
'hotpink',
'indianred',
'indigo',
'ivory',
'khaki',
'lavender',
'lavenderblush',
'lawngreen',
'lemonchiffon',
'lightblue',
'lightcoral',
'lightcyan',
'lightgoldenrodyellow',
'lightgray',
'lightgreen',
'lightgrey',
'lightpink',
'lightsalmon',
'lightseagreen',
'lightskyblue',
'lightslategray',
'lightslategrey',
'lightsteelblue',
'lightyellow',
'lime',
'limegreen',
'linen',
'magenta',
'maroon',
'mediumaquamarine',
'mediumblue',
'mediumorchid',
'mediumpurple',
'mediumseagreen',
'mediumslateblue',
'mediumspringgreen',
'mediumturquoise',
'mediumvioletred',
'midnightblue',
'mintcream',
'mistyrose',
'moccasin',
'navajowhite',
'navy',
'oldlace',
'olive',
'olivedrab',
'orange',
'orangered',
'orchid',
'palegoldenrod',
'palegreen',
'paleturquoise',
'palevioletred',
'papayawhip',
'peachpuff',
'peru',
'pink',
'plum',
'powderblue',
'purple',
'rebeccapurple',
'red',
'rosybrown',
'royalblue',
'saddlebrown',
'salmon',
'sandybrown',
'seagreen',
'seashell',
'sienna',
'silver',
'skyblue',
'slateblue',
'slategray',
'slategrey',
'snow',
'springgreen',
'steelblue',
'tan',
'teal',
'thistle',
'tomato',
'turquoise',
'violet',
'wheat',
'white',
'whitesmoke',
'yellow',
'yellowgreen',
);
if ( in_array( strtolower( $color ), $named_colors ) ) {
return $color;
}
// hex color
if ( preg_match('/^#([a-f\d]{3}){1,2}$/i', $color ) ) {
return $color;
}
// rgb
if ( preg_match( '/rgb\(\s*(?<r>\d{1,3})\s*,\s*(?<g>\d{1,3})\s*,\s*(?<b>\d{1,3})\s*\)/i', $color, $matches ) ) {
$matches['r'] = min( 255, max( 0, (int) $matches['r'] ) );
$matches['g'] = min( 255, max( 0, (int) $matches['g'] ) );
$matches['b'] = min( 255, max( 0, (int) $matches['b'] ) );
return "rgb( {$matches['r']}, {$matches['g']}, {$matches['b']} )";
}
// rgba
if ( preg_match( '/rgba\(\s*(?<r>\d{1,3})\s*,\s*(?<g>\d{1,3})\s*,\s*(?<b>\d{1,3})\s*,\s*(?<a>[\d.]+)\s*\)/i', $color, $matches ) ) {
$matches['r'] = min( 255, max( 0, (int) $matches['r'] ) );
$matches['g'] = min( 255, max( 0, (int) $matches['g'] ) );
$matches['b'] = min( 255, max( 0, (int) $matches['b'] ) );
$matches['a'] = min( 1, max( 0, (float) $matches['a'] ) );
return "rgba( {$matches['r']}, {$matches['g']}, {$matches['b']}, {$matches['a']} )";
}
// hsl
if ( preg_match( 'hsl\(\s*(?<h>[\d.]+)\s*,\s*(?<s>[\d.]+)%\s*,\s*(?<l>[\d.]+)%\s*\)/i', $color, $matches ) ) {
$matches['h'] = min( 360, max( 0, (float) $matches['h'] ) );
$matches['s'] = min( 100, max( 0, (float) $matches['s'] ) );
$matches['l'] = min( 100, max( 0, (float) $matches['l'] ) );
return "hsl( {$matches['h']}, {$matches['s']}%, {$matches['l']}% )";
}
// hsla
if ( preg_match( 'hsl\(\s*(?<h>[\d.]+)\s*,\s*(?<s>[\d.]+)%\s*,\s*(?<l>[\d.]+)%\s*,\s*(?<a>[\d.]+)\s*\)/i', $color, $matches ) ) {
$matches['h'] = min( 360, max( 0, (float) $matches['h'] ) );
$matches['s'] = min( 100, max( 0, (float) $matches['s'] ) );
$matches['l'] = min( 100, max( 0, (float) $matches['l'] ) );
$matches['a'] = min( 1, max( 0, (float) $matches['a'] ) );
return "hsla( {$matches['h']}, {$matches['s']}%, {$matches['l']}%, {$matches['a']} )";
}
// Otherwise, return null!
return null;
}
@timersys
Copy link

hsl and hsla return

preg_match(): Delimiter must not be alphanumeric or backslash

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment