views:

316

answers:

4

What's an efficient way of checking if a username contains a number of special characters that I define.

Examples: % # ^ . ! @ & ( ) + / " ? ` ~ < > { } [ ] | = - ;

I need to detect them and return a boolean, not just strip them out.

Probably a super easy question but I need a better way of doing this than a huge list of conditionals or a sloppy loop.

+1  A: 

With regular expressions the \w special characters means "any word characters" and the \d means digits. The ^ in the brackets means negate or basically anything that isn't in the brackets. The code below would echo "true" or a 1 to indicate the string has non-word characters in it.

$string = '% # ^ . ! @ & ( ) + / " ? ` ~ < > { } [ ] | = - ;'
echo preg_match('~[^\w\d]~', $string);
John Conde
trying to be the fist - you forgot that strings limiting with quotes ;-)
zerkms
Yeah, I caught that. ;)
John Conde
+6  A: 

The better is to determine if there are any chars that are not in an allowed list, like:

preg_match('![^a-z0-9]!i', $nickname);
zerkms
+1: Whitelists are a better security tool than blacklists.
Ben S
Thanks! Excuse my inexperience with regex's but how can I also allow underscores?
pws5068
just add _ after char '9'
zerkms
+3  A: 

Regex is usually the way to go for testing an allowed range, particularly alphanumeric entities such as usernames. However, if the set of disallowed characters is small and/or non-sequential (that is, not easily specified with ranges) you can get better performance with this:

strspn($string,'%#^.!@&()+/"?`~<>{}[]|=-');

This returns the length of the first substring found that is composed of only the disallowed characters (which will be 0 if no disallowed characters are present).

Duncan
+1  A: 

You can use something like the following to count the number of times a character from a given set of characters appears within a string:

<?php

/**
 * Count the number of times any char from $char is found in $search
 * @param $search   Looks for the chars here
 * @param $chars    The chars to look for
 * @return int
 */
function countChars($search, $chars)
{
    $chars = str_replace(
        array("\\", '[', ']', '^', '-'),
        array("\\\\", '\[', '\]', '\^', '\-'), $chars);

    $results = array();
    preg_match_all("/[$chars]/", $search, $results, PREG_SET_ORDER);
    return count($results);
}

var_dump(countChars("Hello, World", "ol"));
var_dump(countChars("Lorem ipsum...", ".m")); // searches for . and m only
var_dump(countChars("^[]-^\\*", "^[]-\\"));

Hope that helps.

icio