Validating form data using regex - php

I'm newest and happy to be here in Stackoverflow. I am following this website since a long time.
I have an input/text field. (e.g. "Insert your name")
The script starts the following controls when the user sends data:
1) Control whether the field is empty or not.
2) Control whether the field goes over maximum characters allowed.
3) Control whether the field contain a wrong matched preg_match regex. (e.g. it contains numbers instead of only letters - without symbols and accents -).
The question is: why if i put this characters "w/", the script doesn't make the control? And it seems like the string bypass controls?
Hello to all guys and sorry if I'm late with the answer (and also for the non-code posted ^^).
Now, talking about my problem. I checked that the problem is on ONLY if I work offline (I use EasyPhp 5.3.6.1). Otherwise the regEx tested online is ok.
This is the code I use to obtain only what I said above:
if (!preg_match('/^[a-zA-Z]+[ ]?[a-zA-Z]+$/', $name)) {
echo "Error";
}
As you can see, this code match:
A string that start (and finish) with only letters;
A string with only 0 or 1 empty space (for persons who has two name, i.e.: Anna Maria);
...right?!
(Please correct me if I am wrong)
Thanks to all!
Wart

My reading of the requirements is
Only letters (upper or lower) can be provided.
Something must be provided (i.e. a non-zero length string).
There is a maximum length.
The code below checks this in a very simple manner and just echos any errors it finds; you probably want to do something more useful when you detect an error.
<?php
$max = 10;
$string = 'w/';
// Check only letters; the regex searches for anything that isn't a plain letter
if (preg_match('/[^a-zA-Z]/', $string)){
echo 'only letters are allowed';
}
// Check a value is provided
$len = strlen($string);
if ($len == 0) {
echo 'you must provide a value';
}
// Check the string is long to long
if ($len > $max) {
echo 'the value cannot be longer than ' . $max;
}

You can also try this:
if (preg_match('/^[a-z0-9]{1,12}/im', $subject)) {
\\ match
}
The above will only match similar to #genesis' post, but will only match if the $subject is between and including 1 - 12 characters long. The regex is also case insensitive.

It works fine.
<?php
$string = '\with';
if (preg_match('~[^0-9a-z]~i', $string)){
echo "only a-Z0-9 is allowed"; //true
}
http://sandbox.phpcode.eu/g/18535/3
You have to make sure you don't put user input into your regex, because that would mean you'll probably check something wrong.

Related

Regex not validating consistently

I'm experiencing an usual problem and I can't seem to nail down the cause. I'm working on server side validation for a number of fields on a signup form on a site. This is the block of PHP:
if ('phone-name' == $tag->name) {
$value = $_POST[$tag->name];
if (!preg_match('/\+([0-9])([ .-]*\d){7,12}/', $value)) {
$result->invalidate($tag, "You must enter a valid number: $value is not valid");
}
}
The regex I am using should only allow the user to input:
the "+" sign
spaces, dots and hyphens
and any number from 0 to 9
However when I run the following tests I get these results:
TEST 1: INVALID INPUT
+3588<script>alert(1)</script>
TEST 2: VALID INPUT
+35388888888<script>alert(1)</script>
Is there something I am missing here? How come the regex works for TEST 2 and not for TEST 1? Any help is much appreciated.
Thanks
Because your regex is matching the number at the beginning of the string. You could use ^$ to match string length (beginning and end), truncate the string first, use strip_tags, etc.
Example:
http://www.regexr.com/3bmfm
^\+([0-9])([ .-]*\d){7,12}$
Remove the ^ and $ from beginning and end of pattern to see it match the second line.
Because you specified how many times a given pattern should be repeated by {7,12}.

How to use preg_match to match everything except numbers in PHP?

Here is my code:
//Validate names have correct characters
if (preg_match("/^[a-zA-Z\s-]+$/i", $_POST['first']) == 0) {
echo '<p class="error">Your first name must only include letters,
dashes, or spaces.</p>';
$okay = FALSE;
}
if(preg_match("/^[a-zA-Z\s-]+$/i", $_POST['last']) == 0) {
echo '<p class="error">Your last name must only include letters,
dashes, or spaces.</p>';
$okay = FALSE;
}
How do I modify this code so that it accepts everything except numbers?
Vedran was most correct. The \d means digits, and the capital \D means NOT digits. So you would have:
if (preg_match("/\d/i", $_POST['first']) > 0) {
echo '<p class="error">Digits are not allowed, please re-enter.</p>';
$okay = FALSE;
}
The above means... If you find any digit... do your error. aka: allow everything except digits.
HOWEVER... I believe you need to re-think your idea to allow "Everything Except digits." You typically don't want the user to enter Quotes or Special ACII Characters, but it appears you want them to be able to enter -!##$%^&*()_+=|}{\][:;<>?,./~
That seems like a long list, but compared to the complete list of possible characters, it isn't that long. So even though it seems like more work, you might want to do that:
if (preg_match("/[^-~`!##$%^&*()+={}|[]\:;<>?,.\w]/i", $_POST['first']) > 0) {
echo '<p class="error">ASCII and Quotes are not accepted, please re-enter.</p>';
$okay = FALSE;
}
Neither one of these have the Beginning/End-Line special characters, because you are looking anywhere in the string for any occurance of (or not of) these checks.
I changed the comparison operator to (if greater than) because we aren't looking for the lack of something required to throw an error anymore, we are looking for the existence of something bad to throw an error.
Also, I took the underscore out of the last regex there... because the Word Character (\w) includes digits, letters, and underscores. Lastly, the dash in the character-class has to be either FIRST or LAST in the list, or it sometimes throws errors or is accidentally mistaken as a range character.
preg_match("/^[^0-9]*$/", $string)
accepts everything but numbers.

how to check a password's Content and length using an array Functions

A user enters a password, say 'tomorrow1234'. I'm aware that I can split it into an array with str_split, but after that, I want to go through each value and search them for things such as capitalization, number, or white space.
How would I go about doing this?
This is an old standby function I use to valiate password complexity. It requires that the password contains upper and lowercase letters, as well as non-alpha characters. Length checks are trivial and are handled elsewhere.
$req_regex = array(
'/[A-Z]/', //uppercase
'/[a-z]/', //lowercase
'/[^A-Za-z]/' //non-alpha
);
foreach($req_regex as $regex) {
if( !preg_match($regex, $password) ) {
return NULL;
}
}
I use the array and a loop so it's easy to add/remove conditions if necessary.
Sounds like your trying to verify password strength.
Check out this web page, your solution would be pretty complex to write a specific answer for, but you can use regex to check for things like capitalization, symbols and digits. This page has several examples you could modify for your needs.
http://www.cafewebmaster.com/check-password-strength-safety-php-and-regex
This is what I would use:
(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$
Checks for 1 letter, 1 number, 1 special character and at least 8 characters long.

Checking for repeated letters in PHP

I am creating a password validation tool, and one of the requirements I'd like is to prevent the user from having too many letters in a row. Any letters, including capital letters, cannot be repeated in a sequence of 3 or more times.
My approach has been to move through the password string with a for loop, and embedding a few checks using regex within that. I can't seem to get the logic to work, and it's probably something simple. Here is one of my (many) failed attempts at cracking this problem:
$seqLetterCounter = 0;
for($i=0; $i < strlen($password); ++$i) {
if($password{$i} == '/([a-zA-Z])/') {
$seqLetterCounter++;
}
if($seqLetterCounter > $this->maxSeqLetters){
$this->errors[6] = 'You have used too many sequential letters in your password. The maximum allowed is ' . $this->maxSeqLetters . '.';
}
if($password{$i} == '/([^a-zA-Z])/') {
$seqLetterCounter = 0;
}
}
$password - a posted value from a form.
$maxSeqLetters - a protected variable that holds an integer value, defined by the user.
errors[] - an array that is used to determine if the password has failed any of the various checks.
Anyone have some pointers?
Fairly simple with a regex:
if (preg_match('/(\w)\1{2,}/', $password)) {
die("3+ repeated chars not allowed");
}
Search for a character (\w), store it (()), then see if that same character comes immediately afterwards (\1) two or more times {2,}.
ok... so if consecutive sets of 3+ letters or numbers are out, then try
/([a-z]{3,}|[0-9]{3,})/i
for the regex instead. Search for any letters ([a-z]) OR (|) numbers ([0-9]), which occur 3 or more times ({3,}), and do the match in a case-insensitive manner (i), so you don't have to worry about aAa breaking the match.

Make sure username is not a phone number

I'm writing a mobile website and I would like the user to be able to login via username or phone number. I think the easist way to validate their response it to not allow them to signup using a phone number as their user name.
The problem is that I'll need to check if the input of the username field is JUST a 10 or 11 digit number. This is where my inexperance in regex comes to my disadvantage. I'm hoping to try something like
function do_reg($text, $regex)
{
if (preg_match($regex, $text)) {
return TRUE;
}
else {
return FALSE;
}
}
$username = $_POST['username'];
if(do_reg($username, '[0-9]{10,11}')){
die('cannot use a 10 or 11 digit number as a username');
}
The above regex is matching all numbers that are 10-11 digits long. I think maybe I need a way to say if the ONLY thing in the user input field is a 10-11 digit number get mad otherwise release the butterflies and rainbows.
EDIT: For the record I decided to make sure the username wasn't JUST a number. Thought this would be simpler and I didn't like the idea of having people use numbers as logins.
So I ended up with
if (!empty($username) && preg_match('/^\d+$/', $username )) {
die('username cannot be a number');
}
Thanks for the help all.
You are almost correct, except PCRE in PHP requires delimiters, and probably some anchors to make sure the field consists only of numbers.
if(do_reg($username, '/^\d{10,11}$/')){
// ^^ ^^
And probably use \d instead of [0-9].
(BTW, you should just call preg_match directly:
if (!preg_match('/^\d{10,11}$/', $username)) {
release('bufferflies', 'rainbows');
}
You need to anchor the regex to match the entire string: ^[0-9]{10,11}$.
^ matches the beginning of a string; $ matches the end.
Limit usernames to only 10 characters and require there username to start with a letter. How would a user write a 10 digit phone number as their username if they are required to enter in at least 1 alpha character (since phone numbers can't start with a 0/o or a 1/l)? (Heck I would require at least 3 alpha chars just to be safe).
When your app gets bigger then you can allow for longer usernames and take into account some of these issues:
Do not use ^ or $ signs if you are only testing the username: if(do_reg($username, '/^\d{10,11}$/')){
The reason I say this is anyone could defeat that by placing a letter in their username, a1235551212
instead use this:
if(do_reg($username, '/\d{10,11}/')){ because that will flag a1235551212d
Also, importantly, remember, that all of these regular expressions are only checking for numbers, there's nothing to stop a user from doing the following: ltwo3for5six7890. Unless of course you limit the username size.
You just should include start and end of the string in the regex
^[0-9]{10,11}$

Categories