homepage Welcome to WebmasterWorld Guest from 174.129.103.100
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
Valid/Invalid Characters in a String
Sp4rkyM4rk




msg:4186164
 9:00 pm on Aug 12, 2010 (gmt 0)

I've been creating a user login system the past few days and all is well, apart from checking for characters in a username. In this thread, I'll use the account creation process as an example. Since the code is long, I'll also remove the rest of the code which checks the password, e-mail address, etc.

I've tried using ereg() to check for characters, but it seems that requires a letter/number to be found in the string and isn't a solution to disallowing other characters.

Example:

if (ereg('[^A-Za-z0-9]', $username))

{

// Continue the code.

}

else

{

trigger_error(U_INVALID_USERNAME);

}


So, this allows 'User NaMe_9&^%$' because all of what it asks for is included. However, I don't want to allow any special characters, nor to I want to make a number mandatory. I want usernames which contain either uppercase letters, lowercase letters, numbers, spaces or underscores to be valid. So the valid version of the example name would be 'User NaMe_9'.

I have also tried using strstr() to search for characters, which seems to work in some cases but not others. 'strstr($username, '!') === FALSE' should disallow use of the exclamation mark in a username, however it doesn't. Moreover, if I can avoid it, I'd rather not have to type out an entire character set of all symbols due to the vast amount of them.

Thanks in advance. :)

 

bedlam




msg:4186171
 9:21 pm on Aug 12, 2010 (gmt 0)

Hi there,

First, ereg() is deprecated as of PHP 5.3.0 [php.net]. You should probably be using preg_match() [php.net] instead.

Secondly, your regular expression is testing for anything that is not an alphanumeric character, so your code should return an error when the ereg expression is true.

[Edit: removed a paragraph. I should read the post thoroughly first!]

-- b

Sp4rkyM4rk




msg:4186177
 9:38 pm on Aug 12, 2010 (gmt 0)

Ah, thanks for that information. I have replaced ereg() with preg_match() and now use:

if (preg_match('/A-Za-z0-9/',$username))

This works fine when filtering out all symbols apart from lowercase, uppercase letters and numbers 0-9. Is there a way to allow spaces and underscores? I have tried:

if (preg_match('/A-Za-z0-9/',$username)) || (preg_match('/ /',$username)) || preg_match('/_/',$username))

but no luck. This allows other symbols again. :(

Matthew1980




msg:4186182
 9:54 pm on Aug 12, 2010 (gmt 0)

Hi there Sp4rkyM4rk,

Check out Rocknbils "Quick lesson in patterns" on preg_match in this thread, I don't fully understand regexp, and I seriously need to set a day aside and learn ;)

Link:[webmasterworld.com ]

Hope that helps you - it explains things for me!

Cheers,
MRb

bedlam




msg:4186189
 10:16 pm on Aug 12, 2010 (gmt 0)

Hello again,

This pattern:

/A-Za-z0-9/

...tells the regex engine to match the exact string 'A-Za-z0-9'. If you're trying to do a character class, you need the square brackets, and something that tells preg_match() to match more than a single character. E.g.:

// Matches one or more alphanumeric characters:
$pattern = '/[a-z0-9]+/i';


-- b

Sp4rkyM4rk




msg:4186207
 11:14 pm on Aug 12, 2010 (gmt 0)

Thanks again for the help. I have read the topic mentioned and taught me a bit about using preg. Although it seems I was wrong when I said '/A-Za-z0-9/' only allows those characters. A name with just symbols such as '^&^$&' will not be valid, however as long the name contains at least one uppercase/lowercase letter or number, other characters are allowed past the validation rule. This is also the case with '[/A-Za-z0-9/]'. :(

EDIT: I think I may have worked out the solution to the problem, but not 100% certain:

'/^[a-zA-Z0-9\_\&\s]+$/'

\s to represent the space, and a backslash between other characters. I decided to include the ampersand in this example, but I'll take it out in the live script (remove \&).

bedlam




msg:4186213
 11:40 pm on Aug 12, 2010 (gmt 0)

Whoops, you're right. My sample will do exactly what you say: match alphanumeric characters anywhere in the string.

Your latest regex should work because you've anchored it at both ends (in human language, your current regex says 'match only if the entire string contains only one or more letters, digits, spaces, underscores or ampersands').

By the way, if you were restricting the string only to letters, digits and underscores, you could also just use '/[\w]+/' I believe...

-- b

rocknbil




msg:4186723
 7:20 pm on Aug 13, 2010 (gmt 0)

Right, but some characters in \w, like underscores, are not letters . . . .


however as long the name contains at least one uppercase/lowercase letter or number, other characters are allowed past the validation rule.


Right, what you're going to want here is a not, but you are likely going to have to do it in two steps. First you make sure it's no invalid characters, then make sure it's at least one letter or number. But let's think ahead - about our poor users who often don't understand our cryptic error messages. :-) Rather than pose an error about characters, let's just CLEANSE the input first, fix it for them, then do the single error check to make sure it's got at least one letter and number.

$username = preg_replace('/[^a-z\d]/i','',$_POST['uname']);

Pregs are about context. When used like this,
'/^blah$/'

^ means "begins with this pattern" and the $ at the end means "ends with this pattern." But when it's the first character within a class [], think of it as meaning "anything not these." So the above means "remove anything that is NOT an upper or lower case character in the range a through z, or a number." The i is a modifier that means make this match case insensitive. \d means any digit, and is the equivalent of 0-9.

So now our string has nothing but letters and numbers.

if ((preg_match('/[a-z]/i',$username) and preg_match('/\d/i',$username))) {
// we're good
}
else {
return_to_form_w_error("<li>User name must contain at least one letter or number.</li>");
}

A working example, except in the interest of TMTOWTDI I used a "not" in the if - if it doesn't match, populate error.


<?php
header("content-type:text/html");
$pwds= Array('ObNoxious','Pret3nti0us','and1MM@ture');
$errstring=$ok=null;
foreach ($pwds as $pwd) {
$pwd = preg_replace('/[^a-z\d]/i','',$pwd);
if (! (preg_match('/[a-z]/i',$pwd) and preg_match('/\d/',$pwd))) {
$errstring .= "<li>The password $pwd is an epic fail.</li>";
}
else { $ok .= "<li>$pwd is OK.</li>"; }
}
echo "<ul>$errstring $ok </ul>";
?>

AlexK




msg:4186763
 8:30 pm on Aug 13, 2010 (gmt 0)


$preg_str_check="#[^][ _A-Za-z0-9-]#";
if( preg_match( $preg_str_check, $some_input ) {
die("I'm not feeling helpful, so buzz off");
}

If anything other than the following characters appear, the
preg_match() will be TRUE:
(space)
(underscore)
a-z (case insensitive)
numeric digits
(hyphen)

If you want to allow any other characters, place them IN FRONT OF the (space). Certain characters (eg `?', `/') need to be escaped (put a back-slash: `\' before them) (wonderfully, if you want a back-slash itself, you will need to use four: `\\\\').

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved