There is an INPUT field, into which a color of the form fff is entered (without the "#" it is inserted in the html itself).

From it, the data is transferred to PHP and that value is directly substituted into HTML. How to filter it correctly?
And to make that if it is invalid, then the standard value is substituted?

  • one
    What color values ​​are valid? The ffff in question ffff not a valid color value in HTML — it must be either 3 or 6 hexadecimal digits. - Sergiks
  • Thank you corrected :) - Red Woolf
  • Options like rgb(255,128,0) do not consider? - Sergiks
  • No, shopping mall in the form of # ***? *** - Red Woolf

5 answers 5

You can check the validity of regular.

For example, such as the color can be set as 3 or 6 characters:

 /^([af]|[AF]|[0-9]){3}(([af]|[AF]|[0-9]){3})?$/i 

Something like this:

 $color; // тут у вас строка с цветом if(preg_match('/^([af]|[AF]|[0-9]){3}(([af]|[AF]|[0-9]){3})?$/i', $color)){ // валидный цвет } else{ // не валидный цвет } 
  • one
    The beginning / end of the line should be added, and then <script>alert('p0wnd')</script>FF9900 will probably pass. - Sergiks
  • @Sergiks Well, yes, corrected the answer. - Suvitruf
  • one
    Why is [af]|[AF]|[0-9] , not [a-fA-F0-9] or not [a-f0-9] ... /i ? - Sergiks
  • @Sergiks don't know, think [a-fA-F0-9] faster? - Suvitruf
  • one
    Your code is not working - you forgot to close the bracket. Added /i but did not remove both options az and AZ . Faster, of course, was a simpler version of the regular season. I checked 3 test runs for 1 million calls for each option. [A-Z0-9] .. /i faster by exactly 20% - Sergiks

We save on matches! preg_match() is considered a slow function. Faster check the length of the string (only 3 or 6), and then the ASCII code of each character in the string:

 <?php function isValidColor( $inputColor) { $len = strlen( $inputColor); // только длиной 3 или 6 if( $len !== 3 && $len !== 6) return false; for( $i=0; $i<$len; $i++) { $code = ord( substr($inputColor, $i, 1)); if( $code >= 97 && $code <= 102) continue; // af if( $code >= 65 && $code <= 70) continue; // AF if( $code >= 48 && $code <= 57) continue; // 0-9 return false; } return true; } 

Ideone with tests.

  • Saving on matches? ) - Suvitruf
  • @Suvitruf right now - yes! - Sergiks
  • For the sake of fairness, I have to say that for some reason this option is wildly slow compared to the regular season: a million calls of f-ii occur on average, over 11s. against 4.5 seconds with a short regular schedule. - Sergiks
  • one
    strlen slow. He does a bunch of extra operations inside. Can be rewritten to isset($inputColor{3}) - Suvitruf
  • @Suvitruf And what will be the result for the string "AAA3XX"? - Yuri Negometyanov

It may be easier:

 function validate_color($str){ return (($l=strlen($str))==3)||($l==6)) && sscanf($str,"%x", $color); } print(validate_color("AAA")? "цвет валидный": "цвет не валидный"); 

PS We remove questions on speed:

 function validate_color_sscan($str){ return ($l=strlen($str)) && (($l==3)||($l==6)) && sscanf($str,"%x", $color); } function test_sscan($str){ for($i=0; $i<2000000; $i++) $v=($l=strlen($str)) && (($l==3)||($l==6)) && sscanf($str,"%x", $color); } function validate_color_preg($str){ return preg_match('/^[A-F0-9]{3}([A-F0-9]{3})?$/i', $str); } function test_preg($str){ for($i=0; $i<2000000; $i++) $v=preg_match('/[a-f0-9]{3}([a-f0-9]{3})?$/i', $str); } print(validate_color_sscan("AAA")? "<br>цвет валидный": "<br>цвет не валидный"); print(validate_color_preg("AAA")? "<br>цвет валидный": "<br>цвет не валидный"); $time0 = microtime(true); test_sscan($str); $time1 = microtime(true); test_preg($str); $time2 = microtime(true); printf("<br>test_sscan x 2000000: %d mcs", $time1-$time0); printf("<br>test_preg x 2000000: %d mcs", $time2-$time1); 

Results:

 color is valid
 color is valid
 test_sscan x 2000000: 8 mcs
 test_preg x 2000000: 14 mcs
  • 5.9 seconds for 1 million calls I got. So far, the record holder is a variant with a regular schedule, but not the one that is in the answer @Suvitruf, but [a-z0-9] with the key /i - Sergiks
  • @Sergiks Such a regular check will not verify anything. Neither the letters nor the register are not taken into account. - Yuri Negometyanov
  • /^[A-F0-9]{3}([A-F0-9]{3})?$/i - I wrote and tested this regular expression. And it is faster than all the other options here, with all the tests. - Sergiks
  • @Sergiks Quite another thing, simply and with taste. I have updated my bit too - Yuri Negometyanov
  • @Sergiks I'm faster - Yuri Negometyanov
  preg_match('/^([a-f0-9]{6}|[a-f0-9]{3})$/i', $color) 

    I wanted to find another alternative option, in addition to regular expressions. Dug up the function ctype_xdigit () - checks whether the string is a hexadecimal value (without the pound sign ). I can not vouch for performance, I did not use it.

     ctype_xdigit('fff'); // true 
    • ctype_xdigit('FFFF'); // true ctype_xdigit('FFFF'); // true is a valid hexadecimal number, but not a valid HTML color. Under the terms of the task, you need to get false if not exactly 3 or 6 characters. - Sergiks