I have a register form which allows users to create usernames and passwords. It requires the username field not be empty, but I need to require that it allow no whitespace at all.
I looked into preg_match() but I can't seem to get that to cooperate with my current code.
if ($_SERVER["REQUEST_METHOD"] == "POST") {
/* Validate Username */
if (empty(trim($_POST["username"]))) {
$username_err = "Username Required";
}
No need to use Regex for something so simple. With strrpos() you can find the last occurence of a substring (space character) in a string (username).
If strrpos doesn't find a match, it will return false. So all you have to do is check if strrpos returns anything else but false:
if (empty(trim($_POST["username"]))) {
$username_err = "Username Required";
} else if (strrpos($_POST["username"], ' ') !== false){
$username_space_err = "Space found in username";
}
Before calling any function on $_POST() I recommend calling isset() on the element to avoid receiving a Notice.
Using isset() will allow for the valid but unlikely username of 0.
Calling trim() on a not-set element will cause a Notice.
I don't see any advantage in checking from the back of the string for spaces with strrpos() so I'll simply call strpos().
If this is a simple pass/fail task (not trying to isolate the cause of the failure), use this:
Code: (Demo)
$_POST['username']="0";
if(isset($_POST['username']) && strlen($_POST['username']) && strpos($_POST['username'],' ')===false){
echo 'pass';
}else{
echo 'fail';
}
Output:
pass
The beauty in this one-liner conditional, is that as soon as one of the conditions fails, the rest are ignored and the fail message will be displayed.
If you want to get a little crazy with micro-optimization, you can remove the strlen() call and just check for the existence of a first character (see if the first "offset" isset).
if(isset($_POST['username'][0]) && strpos($_POST['username'],' ')===false){
echo 'pass';
}else{
echo 'fail';
}
And if we are putting tin-foil hats on, then a check to see that $_POST['username'] is not an array should be included before strpos() is called (in any of the solutions on this page).
if(isset($_POST['username'][0]) && !is_array($_POST['username']) && strpos($_POST['username'],' ')===false){
Related
I am validating a form for my website (still on local server). I used help from w3schools.com mostly. But I noticed that my form accepts an input if the user enters 1 or more space characters.
I know the trim() function remove space from beginning and end of the data and that works fine. But I what a case where a user input only one or more empty whitespace character the php validation will return it as an empty field.
Below a piece of my code:
function sanitize($input){
$input = trim($input);
$input = stripcslashes($input);
$input = htmlspecialchars($input);
return $input;
}
//Full Name Validation
//if field is empty and contains only whitespace
if ($_SERVER["REQUEST_METHOD"] == "POST"){
if (empty($_POST["fname"])){
$fname_err = "Cannot be empty";
}
}
You can use the ctype_space function. It returns true if all of the characters in a string create white space: http://php.net/manual/en/function.ctype-space.php
Try updating your second if statement to also perform the ctype_space check:
//Full Name Validation
//if field is empty and contains only whitespace
if ($_SERVER["REQUEST_METHOD"] == "POST"){
if (empty($_POST["fname"]) || ctype_space($_POST["fname"])){
$fname_err = "Cannot be empty";
}
}
Also, remember to actually call your sanitize function.
So I'm making a webshop, well, trying to atleast for a course project using WAMP. But when trying to register new users and in the process checking their password against a list of common ones the use of fgets() returns an empty string.
if(empty(trim($_POST["password"]))){
...
} elseif (!checkPassword($_POST["password"])) {
$password_err = "Password to common.";
echo "<script>alert('Password to common.'); location.href='index.php';</script>";
}
The checkPassword() is where the fault lies.
function checkPassword($passwordtocheck) {
$passwordtocheck = strtolower($passwordtocheck);
$common_passwords = fopen("commonpasswords.txt", "r");
while(!feof($common_passwords)) {
$check_against = fgets($common_passwords);
echo "<script>alert('Checking $passwordtocheck against $check_against.'); location.href='index.php';</script>";
if($check_against == $passwordtocheck) {
fclose($common_passwords);
return false;
}
}
fclose($common_passwords);
return true;
}
Lets say that I input the password 12345678 when registering, then the scripted alert will say "Checking 12345678 against ." and send me back to index.php. So it looks like it doesn't succeed in reading the file at all. The commonpasswords.txt is in the same folder as the rest of the files and with a single password on each row.
And there is no problem opening the file to begin with either, if I do this instead:
$common_passwords = fopen("commonpasswords.txt", "a");
fwrite($common_passwords, "test");
'test' will appear at the bottom of the file under the existing words on its own row without a hitch. And this is where I'm at, would appreciate whatever input people can give!
EDIT; I do understand that this probably breaks a ton of good-practice 'rules' in general and regarding security. But the website is not really supposed to function or look good, it just need to barely work so that we can later try and use different methods of attacking it and the connected database.
If you insist on doing this yourself – which I do not recommend – you can simplify things a lot by using the file() function. This returns an array of every line in the file. Then use array_filter(); it runs a callback on each element of the array where you can check if there's a match with your password. If the callback returns false, the element is removed from the array. After that, if you have any elements left you know there was a match.
function checkPassword($pwd) {
$pwd = strtolower($pwd);
$common = file("commonpasswords.txt", FILE_IGNORE_NEW_LINES);
$results = array_filter($common, function($i) use ($pwd) {return $i == $pwd;});
return count($results) === 0;
}
But really, there are dozens of libraries out there to check password strength. Use one of them.
Or, as pointed out in the comment, even simpler array_search:
function checkPassword($pwd) {
$pwd = strtolower($pwd);
$common = file("commonpasswords.txt", FILE_IGNORE_NEW_LINES);
return array_search($pwd, $common) === false;
}
I'm a beginner to PHP trying to learn the basics of validating form data. I want to check if the password has been set, and if it has then to further check if it is the right length and has the right characters etc.
//check if set
if (empty($_POST['password']) {
//further validate - check length, characters etc
if (myFunction(($_POST['password'])) {
//success
$password = $_POST['password'];
}
else {
$error = "Password must be at least 8 characters and contain at least one number";
}
}
else {
$error = "Password is required";
}
The problem I'm having is if the user enters "0" as a password, the empty() function treats this as empty, and they're given the "Password is required" error, rather than the "Password must have..." etc error.
Using the isset() function instead wouldn't work either because an empty field would return an empty string, which would be considered to be set.
At the moment I have a workaround where I have a further conditional to check if the password is set to "0", but there must be a more elegant way.
Apologies if this has been covered in another question, I couldn't find anything. Thanks
Use isset() (and possibly strlen(trim()), not empty(). Although the way this code is shown, it will process only an empty password, and give an error to anyone who puts in a password.
if(isset($_POST['password']) && strlen(trim($_POST['password']))){
//process
}else{
//error
}
If you are just learning the basics, then use the function below. However, do remember in a live environment you will want to be hashing passwords properly. Read this link for more info: http://php.net/manual/en/faq.passwords.php
function PasswordCheck($password_string)
{
$password_string = trim($password_string);
if($password_string == '')
{
die("Password not entered");
}
elseif(strlen($password_string) < 8)
{
die("Password must be more than 8 characters in length");
}
elseif(!(preg_match('#[0-9]#', $password_string)))
{
die("Password must contain at least one number");
}
else
{
//Success, now process password
}
}
$password = $_POST['password'];
PasswordCheck($password);
You can use is_null() function or:
if ($_POST['password']==NULL)
please don't forget to use htmlspecialchars once before you use $_POST to make sure no XSS scripting attacK.
Isset function is better than empty in your case.
Additonally if you want user to get at least 8 characters and contain one number, use regular expression it is much better.
0 is considered to be empty in php. (source: http://php.net/empty )
You could get around this by checking if it is empty or if there is nothing in the string, or if it is exactly null, like so:
if ((empty($_POST['password']) || ($_POST['password']=='') ||
($_POST['password']===null) ) {
...
}
This should cover all your bases, however it is easy to check that something is there than checking a negative (I find it cognitively easier), such as making sure the password is entered, instead of checking to see whether it is not entered
The 'PHP Type Comparison Table' is your friend.
http://php.net/manual/en/types.comparisons.php
To check if the password has been set.
// Check if it has been set and contains characters.
if (isset($_POST['password']) && strlen($_POST['password']) > 0)
{
// Passed, now check for the right length, characters, etc.
if (myFunction(($_POST['password']))
{
// Success.
$password = $_POST['password'];
} else {
// Error.
$error = "Password must be at least 8 characters and contain at least one number";
}
} else {
// Failed.
$error = "Password is required";
}
If you require help with your 'myFunction()' function to check length, characters, etc then you will need to post that code as well.
Hope this helps.
please help me..i'm stuck in here..
What i actually want is to check the password from repeating single character or digit.
Requirement for repeating
aaaa = false,
abbb = false
abag = false
a33f = false
abcd1234 = true
there is only once for a character should have in password. If more than once repeated, error returns. So hard to explain.
this is my draft code.
1)first i need to check whether the global configuration for repeating character is allowed or not, if yes my password can have repeating char or digit otherwise it would't. After this, i need to check whether the global configuration for lowercase,uppercase or capitals allowed or not.
if($globalCOnf['repeat_pass']=="yes")//allowed
{
//do nothing
}
else //not allowed
{
//stuck here :(
if(preg_match('/(.)\1{1,}/',$user_input_pass)) //only check "aaaa" not "aba"
{
echo "change password";
}
else
{
if($globalCOnf['having_lower_upper_capital']=="yes")//allowed
{
//do nothing
}
else
{
// can't continue
}
}
}
You can use array_count_values for this (An alternate regex free solution)
<?php
$password = 'abcdfa';
if(max(array_count_values(str_split($password)))>1)
{
echo "Choose another password as words you can't have repeatable characters";
}
OUTPUT:
Choose another password as words you can't have repeatable characters
You get that output because a is repeated two times.
Answer for the question.
if($globalCOnf['repeat_pass']=="yes")//allowed
{
//do nothing
}
else //not allowed
{
if(max(array_count_values(str_split($user_pass)))>1)
{
echo "change your password now!!!";
}
else
{
if($globalCOnf['having_lower_upper_capital']=="yes")//allowed
{
//do nothing
}
else
{
if(preg_match('/[A-Z]/', $user_pass))
{
echo "Can't use uppercase";
}
}
}
}
100% working.. :)
Try something like this -
(\d+).*\1
If you get any match there is a repeated character.
Just allow zero or more characters between two duplicate characters. If there is a match, then the string failed to pass the validation.
Code: (Demo)
$passwords=['aaaa','abbb','abAg','a33f','abcd1234'];
foreach($passwords as $pass){
echo "$pass: ";
if(!preg_match('/([a-zA-Z\d]).*\1/',$pass)){
echo "valid\n";
}else{
echo "failed\n";
}
}
Output:
aaaa: failed
abbb: failed
abAg: valid
a33f: failed
abcd1234: valid
Or as one-line: echo preg_match('/([a-zA-Z\d]).*\1/',$pass)?'failed':'valid'
Using this type of pattern is much more direct that generating a temporary array of characters and counting their occurrences and checking the highest count.
I have this current code that allows me to check the users first name from a registration form to ensure it only contains letters, spaces and dashes. However how can I enable checking multiple fields (e.g. last name too).
/* Checks if the first name only includes letters, dashes or spaces */
if(preg_match("/^[a-zA-Z -]+$/", $_POST['firstname']) == 0)
$errors .="Your name must only include letters, dashes, or spaces.";
I've tried the following but it seems to only check one or the other, not both.
if(preg_match("/^[a-zA-Z -]+$/", $_POST['firstname'], $_POST['lastname']) == 0)
and also:
if(preg_match("/^[a-zA-Z -]+$/", $_POST['firstname'] and $_POST['lastname']) == 0)
Thanks in advance for any suggestions.
Since both of the fields are going to be validated with the same regex and you don't want to return any specific feedback about which one, if any, fails you can simply concatenate the two strings.
if(preg_match("/^[a-zA-Z -]+$/", $_POST['firstname'] . $_POST['lastname']) == 0)
You can use preg_grep, which is preg_match for arrays.
$results = preg_grep('/[^a-zA-Z -]/', $_POST);
if (count($results) > 0) {
die("Some field has invalid characters");
}
But, as AurimasL has pointed out above, you'd probably want to validate each field individually, so you can give better feed back instead of just a blanket "You screwed up, fix it!" error.
Of course, nothing says you can't use this preg_grep as a quick/dirty check for ANY errors, then do individual field checks in case there ARE errors.
You can do this kind of thing using preg_match but it is a very dirty thing because you will never know what is the field that don't respect your rules. You can concatenate the strings like the example:
if(preg_match("/^[a-zA-Z -]+$/", $_POST['firstname'] . $_POST['lastname']) == 0)
Anyway I suggest you to check every field individually and not do this kind of things.
Validate each field
if (preg_match("/^[a-zA-Z\s-]+$/i", $_POST['firstname']) == 0) {
$errors .="Your name must only include letters, dashes, or spaces.";
}
if(preg_match("/^[a-zA-Z\s-]+$/i", $_POST['lastname']) == 0) {
$errors .="Your lastname must only include letters, dashes, or spaces.";
}
Or Both (if user firstname and lastname separated by space)
if(preg_match("/^([a-zA-Z\s-]+)\s+([a-zA-Z\s-]+)$/i",$_POST['lastname'] . $_POST['lastname']) == 0) {
}
The solution to your problem is called: copy and pasting.
You need two if checks, or at least two conditions. You cannot pass two parameters to check onto preg_match.
That's the notation style I would advise you (even if I get some flak for that):
if ( preg_match("/^[a-zA-Z -]+$/", $_POST['firstname'])
and preg_match("/^[a-zA-Z -]+$/", $_POST['lastname']) )
{
...
}
It's important to note that the parenthesis have to be closed around each preg_match(...) call. The outer parens for the if() should stand out. If you are new to the language you should be diligent with formatting.
If you wanted to check for the not matching condition, then preface each preg_match() call with a ! NOT rather.