1

I am trying to get a different error for each type: missing uppercase, missing lower case, missing number, or space. The length seems to be the only thing working. I am guessing because it is at the start of the code. I have tried different variations and can't seem to get it working.

    <?php
    $Passwords = array(
"F!ve5",
"This !s12",
"w!zard12",
"W!ZARD12",
"W!zardJK",
"Wizard12",
"!Qazxsw2",
"@Wsxzaq1",
"@Wsxcde3",
"#Edcxsw2");

foreach ($Passwords as $StongPass) {
echo "<p>The Password &ldquo;" . $StongPass .
    "&rdquo; </p>";
if (strlen($StongPass)<8) 
    echo "Password is to short!";

elseif (strlen($StongPass)>16)
    echo "Password is to long!";

elseif (preg_match('/P[A-Z]/', $StongPass)) 
    echo "Password does not contain an upper case letter!";

elseif (preg_match('/P[a-z]/', $StongPass)) 
    echo "Password does not contain a lower case letter!";

elseif (preg_match('/P[!@#$%^&*()\-_=+{};:,<.>]/', $StongPass)) 
    echo "Password does not contain a special letter!";

elseif (preg_match('/P[0-9]/', $StongPass)) 
    echo "Password does not contain a number!";

elseif (preg_match('/P[""]/', $StongPass)) 
    echo "Password cannot contain any spaces!";

else 
    echo "Password is strong!";

    }
    ?>

The results look like this "The Password “F!ve5” Password is to short! The Password “This !s12” Password is strong! The Password “w!zard12” Password is strong! The Password “W!ZARD12” Password is strong!"

WiseFool
  • 33
  • 5
  • Why the `P` at the start of every regex? These patterns will only match if the string contains `P` immediately before the character you're searching for. –  Jul 31 '15 at 03:27
  • I got rid of the P and added !preg_match this helped except the last four that should be vaild are now say it doesn't match due to a space. – WiseFool Jul 31 '15 at 03:30
  • There is no reason to limit the length of the password or not allow spaces. You should not store the passwords themselves anyway. – Uphill_ What '1 Jul 31 '15 at 08:08

2 Answers2

3

There's a lot of PHP code here that's redundant since the whole validation can be done in a single regular expression by using a series of look-ahead groups.

Using this pattern

/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[,;:])(?=.{8,16})(?!.*[\s])/

each group (between the parentheses) matches an element of the required validation somewhere in the following string and then resets the pointer for the next group. The string thus has to match each group in the pattern to pass.

Broken down to its components we get

^            Make sure we start at the beginning of the string.
(?=.*[A-Z])  Match A-Z in the string
(?=.*[a-z])  Match a-z (separate, since we want at least one of each)
(?=.*[0-9])  Match 0-9
(?=.*[,;:])  Match comma, semicolon or colon. Add additional special characters as required
(?=.{8,16})  Match length between 8 and 16 characters
(?!.*[\s])   Match if whitespace *does not* appear.

In PHP this would become

$pattern = '/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[,;:])(?=.{8,16})(?!.*[\s])/'
$str = "Ab0:padding";
if (preg_match($pattern, $str)) {    //true
  // do stuff
} else {
  // Do other stuff
}

Alternatively:

$pattern = '/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[,;:])(?=.{8,16})(?!.*[\s])/'
$str = "Ab0: padding";
if (preg_match($pattern, $str)) {    // false
  // do stuff
} else {
  // Do other stuff
}

There's an example to play with here

Thanks to Alan Moore for this answer which forms the basis of the above.

Community
  • 1
  • 1
  • I am about to go play with this. I just did an edit with what I got working. I know it is redundant I just wasn't sure how to make it say what was wrong with each array element. That is why it was broke up into so many elseif statements. – WiseFool Jul 31 '15 at 04:08
  • Please anchor your regex. The input passes validation even if there is a new line before the `Ab0:padding` string. There seems to be a bug in PCRE which give the expected result for space followed by `Ab0:padding`, but don't count on that. http://ideone.com/a4RJsF – nhahtdh Jul 31 '15 at 05:45
1

A capital P has no special meaning in a regex. This was kind of a mess. Notice the use of !preg_match() in some cases. I completely rewrote the check for symbols because many of them have special meaning and it is a bit easier to use an ASCII chart to group them.

if (strlen($StongPass)<8) 
    echo "Password is to short!";

elseif (strlen($StongPass)>16)
    echo "Password is to long!";

elseif (!preg_match('/[A-Z]/', $StongPass)) 
    echo "Password does not contain an upper case letter!";

elseif (!preg_match('/[a-z]/', $StongPass)) 
    echo "Password does not contain a lower case letter!";

elseif (!preg_match('/[!-\/:-@[-`{-~]/', $StongPass)) 
    echo "Password does not contain a special letter!";

elseif (!preg_match('/\d/', $StongPass)) 
    echo "Password does not contain a number!";

elseif (preg_match('/\s/', $StongPass)) 
    echo "Password cannot contain any spaces!";

else 
    echo "Password is strong!";
Jacob Phillips
  • 8,841
  • 3
  • 51
  • 66
  • The special character is throwing everything off when I use it this way. I did change to the !preg_match which helped. My issue after that was keeping just perg_match for the space. – WiseFool Jul 31 '15 at 03:42
  • ``'/[!-\/:-@[-`{-~/'`` This makes no sense at all. Did you forget to close the character class? Another thing is that - using range for special character is very confusing to the reader. Just list the characters out. – nhahtdh Jul 31 '15 at 05:29
  • @nhahtdh you're right. I closed the class in the answer. I didn't list them all out because I couldn't remember exactly which chars need escaped. – Jacob Phillips Aug 01 '15 at 00:54