PHP preg_match_all pattern - php

I am using preg_match_all in php to check the characters in the username and password before i add them to the database, but I can't seem to get it to work the way I want. Here is what I have right now:
preg_match_all(USERNAME_PATTERN,$username,$usernameMatches);
preg_match_all(PASSWORD_PATTERN,$password,$passwordMatches);
Here are the patterns, defined as constants:
/*Username and Password Patterns*/
define("USERNAME_PATTERN","[-*_a-z0-9A-Z.]");
define("PASSWORD_PATTERN","[_a-z0-9A-Z]");
I don't know what is wrong with it. Its suppose to check to see if the username has anything other than a-z, A-Z, 0-9, the dash, the astrisk,the underscore, and a period. The password is the same as the username.
Here is the code I use to check:
if ($usernameMatches == 0){
echo("Bad characters in username<br />");
}
The password is the same.

There are several issues with your code.
Your regexes only match a single character.
There are no begin and end anchors in your regex.
Make sure you instantiate the matches array before calling preg_match_all()
Your regex should be surrounded with a / (or other valid char).
Check for a non-match by checking that the array is empty, not by checking if it's equal to zero. There are many type/value checking gotchas in php and it's best to avoid them.
Try this:
/*Username and Password Patterns*/
define("USERNAME_PATTERN","/^[-*_a-z0-9A-Z.]+$/");
define("PASSWORD_PATTERN","/^[_a-z0-9A-Z]+$/");
$usernameMatches = array();
$passwordMatches = array();
preg_match_all(USERNAME_PATTERN,$username,$usernameMatches);
preg_match_all(PASSWORD_PATTERN,$password,$passwordMatches);
if (empty($usernameMatches)){
echo("Bad characters in username<br />");
}
if (empty($passwordMatches)){
echo("Bad characters in password<br />");
}
BTW: Your code could simplified by simply using preg_match() instead of preg_match_all(). Something like this should work as well as your code:
/*Username and Password Patterns*/
define("USERNAME_PATTERN","/^[-*_a-z0-9A-Z.]+$/");
define("PASSWORD_PATTERN","/^[_a-z0-9A-Z]+$/");
if (!preg_match(USERNAME_PATTERN, $username)) {
echo("Bad characters in username<br />");
}
if (!preg_match(PASSWORD_PATTERN, $password)) {
echo("Bad characters in password<br />");
}

Use this:
define("USERNAME_PATTERN","/^[-*_a-z0-9A-Z.]+$/");
define("PASSWORD_PATTERN","/^[_a-z0-9A-Z]+$/");
Currently you allow for single-character usernames and passwords only. Also you have forgotten to encapsulate the regular expressions by / (or another character). (This is specific to PHP and some other languages, admittedly.) I have also added ^ and $ so that the whole input string is matched.
By the way, why bother with checking the passwords? Just require a certain minimum length, for example (but not at all checked for security):
define("PASSWORD_PATTERN","/^.{6,}$/");
Also, I don't get why you're using preg_match_all. A preg_match should do as well, and is probably easier to use:
if (!preg_match(USERNAME_PATTERN, $username) {
echo("Bad characters in username<br />");
}

don't know what is wrong with it. Its suppose to check to see if the username has anything other than a-z, A-Z, 0-9, the dash, the astrisk,the underscore, and a period. The password is the same as the username.
You should check, if passed username/password is valid. You need this pattern. /^[\-\*\w\d\.]{6,12}$/, Here minimum and maximum length is 6 and 12 respectively.
define('PATTERN', '/^[\-\*\w\d\.]+$/');
if(preg_match(PATTERN, $username)){
// username is correct
} else {
// username is wrong.
}
Same for Password.

Before answering I would just say that by asking that question, I suspect that you are saving passwords directly as clear text. This is not a good solution because it exposes your users passwords. There is a discussion around that here with examples on how to do this in a more secure way.
As an added bonus the problem with invalid characters (in the password) will not be an issue for most cases, unless you are dealing with some legacy systems. The reason for this is that you will not store the actual password, but just the generated hash
Back to your question. One alternative I like is to check for the precense of any invalid characters. By adding ^ to the character list, you will match any character other than the list.
define("USERNAME_PATTERN","/[^*_a-z0-9A-Z.-]/");
if(preg_match(USERNAME_PATTERN, $username))
echo 'Bad characters in username';

Related

PasswordHash not working php CI

I followed the tutorial http://dialect.ca/code/ci-simple-login-secure/
but I am having a password error
when I enter the password
M#ndiri%%321 and M#ndiri%%654
at any rate having reversed my password error..
if there is a problem in the regex?
how to fix??..thanks
According to the regex shown above, you shouldn't have anything except alphanumeric characters but as you can see, you have a few special characters in your password string :)
The expression above may be written like this /([a-zA-Z0-9]+)/g as well. Or like this /([[:alnum:]+])/g
If you want to add special characters use this /([ -~]+)/g. This will allow you to use (english) alphanumeric and special characters .
Or use this /([a-zA-Z0-9%##$]+)/g if you want to allow alphanumeric and just the special characters mentioned below in your comment.
How to use the pattern above with PHP
$password = "aH8J9%3$%";
if(!preg_match("/^([a-zA-Z0-9%##$]+)$/", $password)){
echo "Invalid password!";
}
How to use it with JavaScript
var pattern = /^([a-zA-Z0-9%##$]+)$/g;
var password = document.getElementById("password").value; // aH8J9%3$%
if(!pattern.test(password)){
alert("Invalid password!");
}

Accented character validation in PHP

What is a good one-liner php regex for checking first/last name fields with accented characters (in case someone's name was Pièrre), that could match something like:
<?php
$strErrorMessage = null;
if(!preg_match('/\p{L}0-9\s-+/u', trim($_POST["firstname"])))
$strErrorMessage = "Your first name can only contain valid characters, ".
"spaces, minus signs, or numbers.";
?>
This tries to use unicode verification, from this post, but doesn't work correctly. The solution seems pretty hard to google.
Aside from the difficulty to validate a name, you need to put your characters into a character class. /\p{L}0-9\s-+/u matches only on a sequence like "Ä0-9 ------". What you wanted to do is
/^[\p{L}0-9\s-]+$/u
Additionally I added anchors, they ensure that the regex tries to match the complete string.
As ex3v mentioned you should probably add \p{M} to that class to match also combination characters. See Unicode properties.
/^[\p{L}\p{M}0-9\s-]+$/u

Preg_Match false results

OK, so I am working on a login system, and I am working on preventing user input that I don't want, part of my verification is determining that the username is only alphanumeric, as well as the password, as well as a separate verification for the email. So I found several examples to use on php.net because out of everything in php, these preg match things make literally no sense to me what so ever.
The problem I am having is false positives. The first two return false when true, and the email verification works as intended, but for the life of me I don't know why. I could simply remove the ! in front to force my intended answer for the expression, but I actually want to know why two statements structured almost exactly the same return different booleans.
<?php
$user = "testing2";
$pass = "testing1";
$email = "testing#gmail.com";
if (!preg_match('/[^A-Za-z0-9]+/', $user)) {
echo "Username must only contain English letters and numbers<br />";
}
if (!preg_match('/[^A-Za-z0-9]+/', $pass)) {
echo "passw must only contain English letters and numbers<br />";
}
if (!preg_match('/^([a-z0-9])(([-a-z0-9._])*([a-z0-9]))*\#([a-z0-9])*(\.([a-z0-9])([-a-z0-9_-])([a-z0-9])+)*$/i', $email)) {
echo "Please use a valid email";
}
?>
Because you have a negated character class for username and password, you should remove the negation of the condition:
if (preg_match('/[^A-Za-z0-9]/', $user)) { ... }
The above means "if $user contains any characters that are not alphanumeric", so seems to be what you want to warn about. In other words, your first 2 regexes are actually looking for invalid values.
The confusion may arise from the fact that ^ is being used to negate the character classes in the first 2 regexes, but is being used as an anchor (start of string) in the email regex.
An alternative is to make the first 2 regexes consistent with the last, and have them only look for valid values:
if (!preg_match('/^[A-Za-z0-9]+$/', $user)) { ... }
The above makes sure that every character of $user is alphanumeric.
You can do two different things:
look for the correct format; if NOT the string is just alphanumeric chars
if (!preg_match('/[A-Za-z0-9]+/', $user))
look for the incorrect format; if the string contains a not alphanumeric char
if (preg_match('/[^A-Za-z0-9]/', $user))
You mixed them both!

How can I check if preg_match() is False instead of True?

I have this code which makes sure that the username is only letters and numbers. But the way my code is set up, I need it to check if the result of preg_match is false.
Right now it says "if secure echo this". I need its logic to say "if not secure say this". How can I do it?
if (preg_match('/[A-Z]+[a-z]+[0-9]+/', $username))
{
echo 'Secure enough';
}
You can negate the condition like this:
if (!preg_match('/^[A-Za-z0-9]+$/', $username))
{
echo 'Not secure enough';
}
Also, your regex needs to be [A-Za-z0-9]+ if you mean "alphanumeric" (only letters and numbers) as a whole.
The regex in your code would match if the username 1) starts with a capital letter (or more than one) 2) is followed by one or more lower-case letter and 3) ends with one or more number(s).
I'm really not sure if this is what you want. You can do, basically:
if (preg_match('/^[A-Za-z0-9]+$/', $username)) {
echo 'Is only letters and numbers';
} else {
echo 'Contains some other characters';
}
A secure password would be one with special characters and while you probably don't want to enforce this (depending on your target audience), you'd usually want your system to support special characters in passwords.
That's what the ! operator is for, so just say
if (!preg_match.....)
Or this is what the else clause is for. Either way, this is rudimentary programming.

A solid nickname regexp

I want a regular expression to validate a nickname: 6 to 36 characters, it should contain at least one letter. Other allowed characters: 0-9 and underscores.
This is what I have now:
if(!preg_match('/^.*(?=\d{0,})(?=[a-zA-Z]{1,})(?=[a-zA-Z0-9_]{6,36}).*$/i', $value)){
echo 'bad';
}
else{
echo 'good';
}
This seems to work, but when a validate this strings for example:
11111111111a > is not valid, but it should
aaaaaaa!aaaa > is valid, but it shouldn't
Any ideas to make this regexp better?
I would actually split your task into two regex:
to find out whether it's a valid word: /^\w{6,36}$/i
to find out whether it contains a letter /[a-z]/i
I think it's much simpler this way.
Try this:
'/^(?=.*[a-z])\w{6,36}$/i'
Here are some of the problems with your original regex:
/^.*(?=\d{0,})(?=[a-zA-Z]{1,})(?=[a-zA-Z0-9_]{6,36}).*$/i
(?=\d{0,}): What is this for??? This is always true and doesn't do anything!
(?=[a-zA-Z]{1,}): You don't need the {1,} part, you just need to find one letter, and i flag also allows you to omit A-Z
/^.*: You're matching these outside of the lookaround; it should be inside
(?=[a-zA-Z0-9_]{6,36}).*$: this means that as long as there are between 6-36 \w characters, everything else in the rest of the string matches! The string can be 100 characters long mostly containing illegal characters and it will still match!
You can do it easily using two calls to preg_match as:
if( preg_match('/^[a-z0-9_]{6,36}$/i',$input) && preg_match('/[a-z]/i',$input)) {
// good
} else {
// bad
}

Categories