Jump to content

Preg_match help please


Shadowing

Recommended Posts

I tried reading through several threads talking about this but still up in the air about what is going on.

 

I"m doing a online tutor and a guy was using the ereg so i read that PHP no longer uses ereg

so I replaced it with !preg_match

When I do this code it says invalid username

so im thinking it works fine i just need echo"invalid user name in my else statement?

So its like the ereg is the oppiste of prematch?

really appreciate any help with this

 

<?php
if(isset($_POST['Login'])) {

if(!preg_match('[^A-Za-z0-9]',$_POST['name'])){ // before we fetch anything from the database we want to see if the user name is in the correct format.
         echo "Invalid  Username.";
	 }else{

Link to comment
Share on other sites

:code_tags:

 

You need delimiters to make it work. Forward slashes are the most common delimiters

if(!preg_match('/[^A-Za-z0-9]/',$_POST['name']))

 

Also you have a double negative there. You are saying !preg_match and the character class, [], is saying not these characters A-Za-z0-9. Therefore my username joe92 would not match that regex therefore would be output as an invalid username. You need to remove the ^ in the character class.

Link to comment
Share on other sites

Thanks alot for the help

bare with me im a huge noob :)

 

Ya i couldnt figure out why the ^ was in there i just removed that.

I think it is working cause when I log in it says Invalid Username. So that means its working right i just have the double negitive in there?

 

so to fix this I would need to put the else statement on the other side of $query-------------------

is the reason its a double negitive is cause im now using preg_match instead of the ereg?

 

Thanks

 

<?php

if(isset($_POST['Login'])) {

 

if(!preg_match('[A-Za-z0-9]',$_POST['name'])){ // before we fetch anything from the database we want to see if the user name is in the correct format.

        echo "Invalid  Username.";

}else{

 

$query = "SELECT password,id,login_ip FROM users WHERE name='".mysql_real_escape_string($_POST['Username'])."'";

$result = mysql_query($query) or die(mysql_error());

$row = mysql_fetch_array($result); // Search the database and get the password, id, and login ip that belongs to the name in the username field.

Link to comment
Share on other sites

The ^ character defines the start of the pattern and $ defines the end.

 

 preg_match("/^[a-zA-Z0-9]+$/") 

 

Not sure if it makes a difference but i would always put the ^ outside of the square brackets.

 

For your logic don't you want:

 


If (pregmatch(blah blah))   //i.e. if the prematch satisfies what you want from the username grab query

{
grab database stuff
}

else {
invalid user

}

 

Thanks alot for the help

bare with me im a huge noob :)

 

Ya i couldnt figure out why the ^ was in there i just removed that.

I think it is working cause when I log in it says Invalid Username. So that means its working right i just have the double negitive in there?

 

so to fix this I would need to put the else statement on the other side of $query-------------------

is the reason its a double negitive is cause im now using preg_match instead of the ereg?

 

Thanks

 

<?php

if(isset($_POST['Login'])) {

 

if(!preg_match('[A-Za-z0-9]',$_POST['name'])){ // before we fetch anything from the database we want to see if the user name is in the correct format.

        echo "Invalid  Username.";

}else{

 

$query = "SELECT password,id,login_ip FROM users WHERE name='".mysql_real_escape_string($_POST['Username'])."'";

$result = mysql_query($query) or die(mysql_error());

$row = mysql_fetch_array($result); // Search the database and get the password, id, and login ip that belongs to the name in the username field.

Link to comment
Share on other sites

The reason it was a double negative of sorts is because you have a ! in front of preg_match, meaning if not. You also had a ^ in your expression which in the location you had it means if not.

 

Besides this though, I don't see the point in validating a username in this situation. You should be validating the data on the way into the database. If you do that, you don't need to validate it again when looking it up.

Link to comment
Share on other sites

Please use code tags when posting code. Its the button with a picture of the hash symbol '#'. It makes it so much easier to read.

 

Ereg functions use POSIX language in the pattern. Preg functions use PCRE language in the pattern. That is the difference between the two.

 

The reason it is still not working is because you haven't placed the pattern in delimiters. Secondly the pattern will match once and return true as there is no repetition, so usernames such as o"£$%^&* would match because the o at the beginning would be matched and the engine would stop reading. To match the entire username you will have to tell the pattern to repeat. If your standards are a minimum length of 5 and a maximum of 20 for your usernames, this would become

if(!preg_match('/[A-Za-z0-9]{5,20}/',$_POST['name']))

 

However, you will still have a problem in that names such as obiwan"£$%^&* will still match because the first 5 characters are proper characters so the function will return true. To get around this, you want to tell your regex that the start till the end of $_POST['name'] are all to be matched in the regex. You would do that by placing a ^ at the start and a $ at the end, making it

if(!preg_match('/^[A-Za-z0-9]{5,20}$/',$_POST['name']))

 

The ^ character defines the start of the pattern

Actually, in a character class it denotes 'not the following characters'. I.e. [^a] would mean not a.

Link to comment
Share on other sites

Oh wow thanks guys. You guys are awesome.

so i just get rid of the ! and now the logic works

 

I got this code from a tutor im doing on making a web browser game and this is his code he was using that didnt work for me since the ereg that he used no longer works in PHP5.3

 

i need to do more PHP tutors i guess cause i had no idea that the ! turns the if statement around.

 

Yah sorry about the code posting i was trying to look for the code symbol. It was one of the few buttons I didnt try lol :)

Link to comment
Share on other sites

Joe thank you so much for taking the time out to explain to me in detail. was major help!

 

My only problem now is i cant figure out how to test it to see if it works.

When I type in bad characters it tells me Account doesn't exist. Like it should of course.

why doesnt it echo both statements? or maybe its cause its still not working.

here is my entire code for this

 

<?php
if(isset($_POST['Login'])) {

if(preg_match('/^[A-Za-z0-9]{5,20}/',$_POST['name'])){ // before we fetch anything from the database we want to see if the user name is in the correct format.
         echo "Invalid  Username.";
	 }else{

		 $query = "SELECT password,id,login_ip FROM users WHERE name='".mysql_real_escape_string($_POST['Username'])."'"; 
$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_array($result); // Search the database and get the password, id, and login ip that belongs to the name in the username field.

if(empty($row['id'])){
// check if the id exist and it isn't blank.
    echo "Account doesn't exist.";
}else{

	if(md5($_POST['password']) != $row['password']){
		// if the account does exist this is matching the password with the password typed in the password field. notice to read the md5 hash we need to use the md5 function.
            echo "Your password is incorrect."; 
		}else{

			if(empty($row['login_ip'])){ // checks to see if the login ip has an ip already 
	$row['login_ip'] = $_SERVER['REMOTE_ADDR'];
	}else{

	$ip_information = explode("-", $row['login_ip']); // if the ip is different from the ip that is on the database it will store it

	if (in_array($_SERVER['REMOTE_ADDR'], $ip_information)) {	
	$row['login_ip'] = $row['login_ip'];
	}else{	
	$row['login_ip'] = $row['login_ip']."-".$_SERVER['REMOTE_ADDR'];
	}

Link to comment
Share on other sites

The ! in php means 'not'. Your if statement no longer includes the ! so it is matching the user name in the preg_match and executing the echo rather than the mysql executions. Incorrect names such as $%^& are not matching the preg_match so are being executed in the else. They then don't match any records in the database so echo 'Account doesn't exist'. Its the wrong way round. What would logically make sense in my head would be to keep the preg_match like it is but rearrange the other code. I.e.

<?php
if(isset($_POST['Login'])) {
if(preg_match('/^[A-Za-z0-9]{5,20}/',$_POST['name'])){ // before we fetch anything from the database we want to see if the user name is in the correct format.
        $query = "SELECT password,id,login_ip FROM users WHERE name='".mysql_real_escape_string($_POST['Username'])."'"; 
        //do all the other mysql stuff
    }
else{
        echo 'Invalid Username.';
    }

 

To keep it in your format though will require you placing the ! back at the start of the preg_match since that regex is looking for correct characters.

 

Furthermore, you will need to place the $ at the end of the pattern otherwise scenario two of my previous post with the username obiwan"£$%^&* will still be matched. Use this as the pattern

/^[A-Za-z0-9]{5,20}$/

Link to comment
Share on other sites

Oh yah thats right cause Thorpe said i had the ('/[^A-Za-z0-9] instead of  ('^/[A-Za-z0-9] which was cancling the ! out lol. I dont know why i was thinking i had to move the ^ and delete the ! lol cause that would put me back to where i was at.

 

I tested this code out and it still says invalid username

guess i can just switch the "else" around cause I do perfer it switched around to. it bugs me not knowing why this way doesnt work though or am I still in error?

 

if(!preg_match('/^[A-Za-z0-9]{5,20}$/',$_POST['name'])){ // 
         echo "Invalid  Username.";
	 }else{

Link to comment
Share on other sites

Can you give an example of the input please?

 

Can you also make sure that $_POST['name'] is what you want it to be. Put

print_r($_POST['name']);

before the if statement to print it at the top of the page, and make sure it is the required/designated field.

 

 

Just wanna throw out there that if you're simply looking to see if $_POST['name'] only has letters or numbers and you there is no length limit etc.. you don't even need to use regex, just use ctype_alnum

 

if (ctype_alnum($_POST['name'])) {
  // it's good, do something
} else {
  // it's bad, do something
}

 

Ha, never knew about that ctype. Thats a handy little set of functions!

Link to comment
Share on other sites

My imput is Shadowing

tried putting print_r($_POST['name']); in a few places i must be putting it in the wrong spot. sorry i know im getting spoon fed here :)

 

<?php
if(isset($_POST['Login'])) {
print_r($_POST['name']);
if(!preg_match('/^[A-Za-z0-9]{5,20}$/',$_POST['name'])){ // 
         echo "Invalid  Username.";
	 }else{

 

 

 

Here is the code with the html with it

 

 

<? include_once("connect.php"); ?>

<html>
<body>

<?php
if(isset($_POST['Login'])) {

if(!preg_match('/^[A-Za-z0-9]{5,20}$/',$_POST['name'])){ // before we fetch anything from the database we want to see if the user name is in the correct format.
         echo "Invalid  Username.";
	 }else{

		 $query = "SELECT password,id,login_ip FROM users WHERE name='".mysql_real_escape_string($_POST['Username'])."'"; 
$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_array($result); // Search the database and get the password, id, and login ip that belongs to the name in the username field.

if(empty($row['id'])){
// check if the id exist and it isn't blank.
    echo "Account doesn't exist.";
}else{

	if(md5($_POST['password']) != $row['password']){
		// if the account does exist this is matching the password with the password typed in the password field. notice to read the md5 hash we need to use the md5 function.
            echo "Your password is incorrect."; 
		}else{

			if(empty($row['login_ip'])){ // checks to see if the login ip has an ip already 
	$row['login_ip'] = $_SERVER['REMOTE_ADDR'];
	}else{

	$ip_information = explode("-", $row['login_ip']); // if the ip is different from the ip that is on the database it will store it

	if (in_array($_SERVER['REMOTE_ADDR'], $ip_information)) {	
	$row['login_ip'] = $row['login_ip'];
	}else{	
	$row['login_ip'] = $row['login_ip']."-".$_SERVER['REMOTE_ADDR'];
	}
	}
		}
		}
}
}
?>

<form id="form1" name="form1" method="post" action=""><center>
  GAME LOGIN
  <br />
  <br />
  Username:
  <input type="text" name="Username" id="Username" />
  <br />
  <br />
Password:
<input type="password" name="password" id="password" />
  <br />
  <br />
  <input type="submit" name="Login" id="Login" value="Login" />
  </center>
</form>

</body>
</html>

Link to comment
Share on other sites

The mistake lies in that are referencing the wrong name.

 

<input type="text" name="Username" id="Username" />

That is your username field, it has a name 'Username'. The name of an input field is what you place in the quotation marks when you wish to receive it. Hence, you need to change your $_POST['name'] to

 

$_POST['Username']

 

If you change the print to just print_r($_POST); it shall show you all of the post in an array. This is very helpful in bug finding.

 

Hope this helps,

Joe

Link to comment
Share on other sites

Nice Joe that fixed it

 

Yah that makes total sense lol.

so that was just a typo then on that tutor.

 

good thing I decided to include the html.

 

Honestly im glad all this happend. Cause now I understand this script way better now. where before it was really alien like to me when I started this thread lol.

 

thanks alot guys seriously for taking the time out to help people like me on just getting started with Programing.

Link to comment
Share on other sites

I figure i should go ahead and mention this

 

I notice

if(!preg_match('/^[A-Za-z0-9]{5,20}$/',$_POST['Username']

 

and

 

if(preg_match('/^[^A-Za-z0-9]{5,20}$/',$_POST['Username']

 

isnt the same thing.

 

Not using the ! and putting the ^ by the A doesnt make it work.

cause someone mention adding the ^ in that spot was the same thing as adding the ! before preg_match

Link to comment
Share on other sites

if (!preg_match('/^[^A-Za-z0-9]{5,20}$/',$_POST['Username'])

 

! This means the inverse of what is returned from preg_match().  preg_match() without a 3rd argument will return true if a match occurred, false if no match. So putting the ! in front of it inverses that for the "if(...)" condition.  So if preg_match() returns true (match occurred), and you have ! in front of preg_match, the expression inverts that to false, so the condition evaluates false. 

 

^ outside of the [...] this signifies start of string anchor tag (or start of line if you use a modifier, but that's another can of worms).  This is, coupled with the $ (end of string/line counterpart) ensures that the match is being performed on the whole string, not just a substring within the string.

 

^ The [...] brackets is called a character class. It's basically a list of characters to match for.  Having a ^ at the start  [^...] means to match anything NOT within the [...] brackets (which makes it a negative character class).

 

 

Link to comment
Share on other sites

So wouldnt

(!preg_match('/^[A-Za-z0-9]{5,20}$/'

and

(preg_match('/^[^A-Za-z0-9]{5,20}$/'

 

be saying the same thing?

 

cause

(preg_match('/^[^A-Za-z0-9]{5,20}$/'

 

doesnt work it comes up as invalid username. so its like the [^A-Za-z0-9] isnt making any affect at all

Link to comment
Share on other sites

wait

(!preg_match('/^[^A-Za-z0-9]{5,20}$/'

does turn it around and make it display invalid user name like it should

 

(preg_match('/^[^A-Za-z0-9]{5,20}$/'

 

acts like the ^ isnt even there

 

so

(preg_match('/^[^A-Za-z0-9]{5,20}$/'

and

(preg_match('/^[A-Za-z0-9]{5,20}$/'

is giving the same results

 

maybe php just doesnt let that get turned around like that?

which makes sense there is no reason someone would use a double negitive like that anyways

Link to comment
Share on other sites

Okay so here is a tl;dr....

 

First off, a couple things to understand:

 

To clarify preg_match() return values: With no 3rd argument, preg_match() returns integer value of 1, 0 or boolean value of false.  "false" only happens if it returns an error from parsing (like you forgot a delimiter or something) so for these examples, the "false" output is never because of this, because the syntax is correct.  IOW in these examples, preg_match() itself always returns an integer value of 1 or 0.

 

2nd point is that ! is the logical NOT operator. It returns a boolean false if the expression evaluates true, and a boolean true if the expression evaluates false.  1 evaluates true and 0 evaluates false.  So for instance, if preg_match were to return an integer of 1 because it matched something but you have a ! in front of it, 1 is true so the ! will return a boolean false. 

 

3rd point is that two of these are "right", if you put your "give error" code vs. "perform query" code in the right place based on the logic.  But one of them is more clear, based on how people read things in general, or how the rest of your code is setup.  So even though there are multiple "right answers" per se, you should pick the version that clearly conveys your intentions and makes the code easiest to read.  Also, there are two wrong answers here, which are demonstrated in the code examples below.

 

4th point is that when I refer to "valid" or "invalid" string (the posted username), there are 2 different contexts: 1) what YOU intend to be valid (a username with only letters or numbers, 5 to 20 chars long), and 2) what the regex pattern considers an (in)valid match.  Hopefully you can see from the context what I mean, and I also try to be explicit for the most part.  This is important to understand, so that you can understand why the two wrong answers are wrong.

 

 

So.... based on those things, let's look at the examples

 

1) positive char class with logical NOT operator

 

The regex matches for 5 to 20 numbers or letters, and the NOT operator inverts the result

 

var_dump(!preg_match('/^[A-Za-z0-9]{5,20}$/','12345')); // output: bool (false)
var_dump(!preg_match('/^[A-Za-z0-9]{5,20}$/','123')); // output: bool (true)
var_dump(!preg_match('/^[A-Za-z0-9]{5,20}$/','.....')); // output: bool (true)

 

  • '12345' is valid to you AND to the regex (right chars, right length). preg_match() returns an integer value of 1, which evaluates true, but the ! operator inverts that and returns a boolean false.
  • '123' is invalid to the regex AND to you (right chars, wrong length). preg_match() returns an integer value of 0, which evaluates false, but the ! operator inverts that and returns a boolean true.
  • '.....' is invalid to the regex AND to you (wrong chars, right length). preg_match() returns an integer value of 0, which evaluates false, but the ! operator inverts that and returns a boolean true.

 

The following codeblock will technically work, but it is not very clear, because it's evaluating "true" on what you consider to be invalid usernames :

 

if ( !preg_match('/^[A-Za-z0-9]{5,20}$/',$_POST['Username']) ) {
  // will execute if username '123'
  // will execute if username '.....'
} else {
  // will execute if username '12345'
}

 

 

2) negative char class with logical NOT operator

 

The regex matches for 5 to 20 of anything NOT a number or letter, and the NOT operator inverts the result.

 

var_dump(!preg_match('/^[^A-Za-z0-9]{5,20}$/','12345')); // output: bool (true)
var_dump(!preg_match('/^[^A-Za-z0-9]{5,20}$/','123')); // output: bool (true)
var_dump(!preg_match('/^[^A-Za-z0-9]{5,20}$/','.....')); // output: bool (false)

 

  • '12345' is valid to you (right chars, right length) but invalid to the regex (wrong chars, right length). preg_match() returns an integer value of 0, which evaluates false, but the ! operator inverts that and returns a boolean true.
  • '123' is invalid to you (right chars, wrong length) and invalid to the regex (wrong chars, wrong length). preg_match() returns an integer value of 0, which evaluates false, but the ! operator inverts that and returns a boolean true.
  • '.....' is invalid to you (wrong chars, right length) but valid to the regex (right chars, right length). preg_match() returns an integer value of 1, which evaluates true, but the ! operator inverts that and returns a boolean false.

 

This will not work in an if..else because your expectations and the regex's expectations do not line up 100%, so you will end up with false positives!

 

// bad!
if ( !preg_match('/^[^A-Za-z0-9]{5,20}$/',$_POST['Username']) ) {
  // will execute if username is '12345'
  // will execute if username is '123'
} else {
  // will execute if username is '.....'
}

 

 

 

3) Positive char class without logical NOT operator

 

The regex matches for 5 to 20 numbers or letters

 

var_dump(preg_match('/^[A-Za-z0-9]{5,20}$/','12345')); // output: int (1)
var_dump(preg_match('/^[A-Za-z0-9]{5,20}$/','123')); // output: int (0)
var_dump(preg_match('/^[A-Za-z0-9]{5,20}$/','.....')); // output: int (0)

 

  • '12345' is valid to you and the regex (right chars, right length). preg_match() returns an integer value of 1, which evaluates true
  • '123' is invalid to you and the regex (right chars, wrong length). preg_match() returns an integer value of 0, which evaluates false
  • '.....' is invalid you and the regex (wrong chars, right length). preg_match() returns an integer value of 0, which evaluates false

 

The following codeblock will work, and the intention is clear: "if the username is valid, do this..otherwise do this"

 

if ( preg_match('/^[A-Za-z0-9]{5,20}$/',$_POST['Username']) ) {
  // will execute if username '12345'
} else {
  // will execute if username '123'
  // will execute if username '.....'
}

 

 

4) negative char class without logical NOT operator

 

The regex matches for 5 to 20 of anything NOT a number or letter

 

var_dump(preg_match('/^[^A-Za-z0-9]{5,20}$/','12345')); // output: int (0)
var_dump(preg_match('/^[^A-Za-z0-9]{5,20}$/','123')); // output: int (0)
var_dump(preg_match('/^[^A-Za-z0-9]{5,20}$/','.....')); // output: int (1)

 

  • '12345' is valid to you (right chars, right length) but invalid for the regex (wrong chars, right length). preg_match() returns an integer value of 0, which evaluates false
  • '123' is invalid to you (right chars, wrong length) and invalid for the regex (wrong chars, wrong length). preg_match() returns an integer value of 0, which evaluates false
  • '.....' is invalid you (wrong chars, wrong length) but valid for the regex (right chars, right length). preg_match() returns an integer value of 1, which evaluates true

 

 

This will not work in an if..else because your expectations and the regex's expectations do not line up 100%, so you will end up with false negatives!

 

// bad!
if ( preg_match('/^[^A-Za-z0-9]{5,20}$/',$_POST['Username']) ) {
  // will execute if username is '.....'
} else {
  // will execute if username is '12345'
  // will execute if username is '123'
}

 

 

 

 

Link to comment
Share on other sites

ohhhhh

Thanks Josh for taking the time out in seperating all that.

lol that was an amazing comparision of all possible ways.

 

that would of ate at me for ever for not knowing.

 

I ran some test and this code works exactly how you said it would.

 

( preg_match('/^[^A-Za-z0-9]{5,20}$/',$_POST['Username']) ) {

 

Maybe since im a noob im trying to understand it to deep to fast. but im affraid of making mistakes ha :) So its like i have to know every end to end situation.

Link to comment
Share on other sites

Route 3 of josh's explanation is by far the easiest route to logically follow. And when you return to your own script in a weeks time or more, being able to logically understand and follow it will save you so much time and stress. Structure your scripts in accordance with route 3 :)

Link to comment
Share on other sites

Ive been reading alot of tutors and guides online and something puzzles me about this code

Isnt typing two if statements not correct or poor technic?

 

shouldnt it be more like

 

If this and that happends

&&

this and that happends

 

instead of

 

If this and that happends

If this and that happends

 

Cause with two If statments next to each other it really confusing how these "}" are working in the script

caue of the 6's } at the bottom of the script

 

 

 

 

<? include_once("connect.php"); ?>

<html>
<body>

<?php
if(isset($_POST['Login'])) {

if(!preg_match('/^[A-Za-z0-9]{5,20}$/',$_POST['Username'])){ // before we fetch anything from the database we want to see if the user name is in the correct format.
         echo "Invalid  Username.";
	 }else{			 
		 $query = "SELECT password,id,login_ip FROM users WHERE name='".mysql_real_escape_string($_POST['Username'])."'"; 
$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_array($result); // Search the database and get the password, id, and login ip that belongs to the name in the username field.

if(empty($row['id'])){
// check if the id exist and it isn't blank.
    echo "Account doesn't exist.";
}else{

	if(md5($_POST['password']) != $row['password']){
		// if the account does exist this is matching the password with the password typed in the password field. notice to read the md5 hash we need to use the md5 function.
            echo "Your password is incorrect."; 
		}else{

			if(empty($row['login_ip'])){ // checks to see if the login ip has an ip already 
	$row['login_ip'] = $_SERVER['REMOTE_ADDR'];
	}else{

	$ip_information = explode("-", $row['login_ip']); // if the ip is different from the ip that is on the database it will store it

	if (in_array($_SERVER['REMOTE_ADDR'], $ip_information)) {	
	$row['login_ip'] = $row['login_ip'];
	}else{	
	$row['login_ip'] = $row['login_ip']."-".$_SERVER['REMOTE_ADDR'];
	}
	}
		}
		}
}
}
?>

 

 

 

 

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.