I'm asking if there are better ways of determining what string has been inputted, either a phone number or an email, here are my already working code
public function InviteFriend($invitation)
{
// Initialize Connection
$conn = $this->conn;
// Check what type of Invitation it is
if (preg_match_all('~\b\d[- /\d]*\d\b~', $invitation, $res) > 0) {
$type = 'phone';
} else if (preg_match_all('/^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/i', $invitation, $res) > 0) {
$type = 'email';
}
echo $type;
}
But my concern is if a user typed both phone and email in the same string, which of the if statement would be picked and which would be ignored? and is my way of determining which type of string proper or is there a more efficient way?
Thanks
There are two anchors almost available in all regex flavors which you have used in your second regex for validating an email address, shown as ^ and $ and meant as beginning and end of input string respectively.
You should use them for first validation as well. Your phone number validation lacks a good validation since it validates an arbitrary sequence of strings like 1------- --------5 that doesn't look like a phone number and much more things since it doesn't match against whole string (missing both mentioned anchors). So I used \d{10} to indicate a 10-digit phone number that you may want to change it to meet your own requirements, this time more precisely.
You don't really want that kind of email validation either. Something more simpler is better:
public function InviteFriend($invitation)
{
if (preg_match('~^\d{10}$~', $invitation)) {
$type = 'phone';
} else if (preg_match('~^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$~i', $invitation)) {
$type = 'email';
}
echo $type ?? 'Error';
}
Related
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 am trying to find the common errors users have while entering email ids. I can always validate EMAIL using PHP Email Filter
$email = "someone#exa mple.com";
if(!filter_var($email, FILTER_VALIDATE_EMAIL))
{
echo "E-mail is not valid";
}
else
{
echo "E-mail is valid";
}
or pattern matching
$email = test_input($_POST["email"]);
if (!preg_match("/([\w\-]+\#[\w\-]+\.[\w\-]+)/",$email))
{
$emailErr = "Invalid email format";
}
I agree that these are not full proof ways to validate emails. However they should capture 80% of cases.
What I want is - Which position email became invalid? if its a space, at what position user had entered space. or did it fail because of "." in the end?
Any pointers?
-Ajay
PS : I have seen other thread regarding email validations. I can add complexity and make it 100%. concern here is to capture the most common mistakes made by people when entering Email ID.
This is difficult because sometimes it's not always a single character that makes an email address invalid. The example you give could easily be solved by:
$position = strpos('someone#exa mple.com', ' ');
However, it seems you are not interested in an all encompassing solution but rather something that will catch the majority of character based errors. I would take the approach of using the regular expression but capture each section of the email address in a sub pattern for further validation. For example:
$matches = null;
$result = preg_match("/(([\w\-]+)\#([\w\-]+)\.([\w\-]+))/", $email, $matches);
var_dump($matches);
By capturing sections of the regex validation in sub patterns you could then dive further into each section and run similar or different tests to determine where the user went wrong. For example you could try and match up the TLD of the email address against a whitelist. Of course there are also much more robust email validators in frameworks like Zend or Symfony that will tell you more specifically WHY an email address is not valid, but in terms of knowing which specific character position is at fault (assuming it's a character that is at fault) I think a combination of tactics would work best.
There is no way I know of in Java to report back the point at which a regex failed. What you could do is start building a set of common errors (as described by Manu) that you can check for (this might or might not use regex expressions). Then categorize into these known errors and 'other', counting the frequency of each. When an 'other' error occurs, develop a regex that would catch it.
If you want some assistance with tracking down why the regex failed you could use a utility such as regexbuddy, shown in this answer.
Just implement some checks on your own:
Point at the end:
if(substr($email, -1) == '.')
echo "Please remove the point at the end of you email";
Spaces found:
$spacePos = strpos($email, ' ');
if(spacePos !== false)
echo "Please remove the space at pos: ".$spacePos;
And so on...
First of all, I would like to say that the reason your example fails is not the space. It is the lack of '.' in former part and lack of '#' in the latter part.
If you input
'someone#example.co m' or 's omeone#example.com', it will success.
So you may need 'begin with' and 'end with' pattern to check strictly.
There is no exist method to check where a regular expression match fails as I know since check only gives the matches, but if you really want to find it out , we can do something by 'break down' the regular expression.
Let's take a look at your example check.
preg_match ("/^[\w\-]+\#[\w\-]+\.[\w\-]+$/",'someone#example.com.');
If it fails, you can check where its 'sub expression' successes and find out where the problem is:
$email = "someone#example.com.";
if(!preg_match ("/^[\w\-]+\#[\w\-]+\.[\w\-]+$/",$email)){ // fails because the final '.'
if(preg_match("/^[\w\-]+\#[\w\-]+\./",$email,$matches)){ // successes
$un_match = "[\w\-]+"; // What is taken from the tail of the regular expression.
foreach ($matches as $match){
$email_tail = str_replace($match,'',$email); // The email without the matching part. in this case : 'com.'
if(preg_match('/^'.$un_match.'/',$email_tail,$match_tails)){ // Check and delete the part that tail match the sub expression. In this example, 'com' matches /[\w\-]+/ but '.' doesn't.
$result = str_replace($match_tails[0],'',$email_tail);
}else{
$result = $email_tail;
}
}
}
}
var_dump($result); // you will get the last '.'
IF you understand the upper example, then we can make our solution more common, for instance, something like below:
$email = 'som eone#example.com.';
$pattern_chips = array(
'/^[\w\-]+\#[\w\-]+\./' => '[\w\-]+',
'/^[\w\-]+\#[\w\-]+/' => '\.',
'/^[\w\-]+\#/' => '[\w\-]+',
'/^[\w\-]+/' => '\#',
);
if(!preg_match ("/^[\w\-]+\#[\w\-]+\.[\w\-]+$/",$email)){
$result = $email;
foreach ($pattern_chips as $pattern => $un_match){
if(preg_match($pattern,$email,$matches)){
$email_tail = str_replace($matches[0],'',$email);
if(preg_match('/^'.$un_match.'/',$email_tail,$match_tails)){
$result = str_replace($match_tails[0],'',$email_tail);
}else{
$result = $email_tail;
}
break;
}
}
if(empty($result)){
echo "There has to be something more follows {$email}";
}else{
var_dump($result);
}
}else{
echo "success";
}
and you will get output:
string ' eone#example.com.' (length=18)
I am new to PHP (not programming overall), and having problems with this simple line of code. I want to check whether some input field has been filled as anysymbolornumber#anysymbolornumber just for checking whether correct email was typed. I don't get any error, but the whole check system doesn't work. Here is my code and thanks!
if ($email = "[a-zA-Z0-9]#[a-zA-Z0-9]")
{
Since your new to php , i suggest you should buy a book or read an tutorial or two.
For email validation you should use filter_var an build in function that comes with with php 5.2 and up :
<?php
if(!filter_var("someone#example....com", FILTER_VALIDATE_EMAIL)){
echo("E-mail is not valid");
}else{
echo("E-mail is valid");
}
?>
you can use other functions .. instead of regular expressions
if(filter_var($email,FILTER_VALIDATE_EMAIL)){
echo "Valid email";
}else{
echo "Not a valid email";
}
As correctly pointed out in the comments, the regex you are using isn't actually a very good way of validating the email. There are much better ways, but if you are just wanting to get a look at how regular expressions work, it is a starting point. I am not an expert in regex, but this will at least get your if statement working :)
if(preg_match("[a-zA-Z0-9]#[a-zA-Z0-9]",$email)
{
// Your stuff
}
It looks like you're trying to verify that an email address matches a certain pattern. But you're not using the proper function. You probably want something like preg_match( $pattern, $target ).
Also, your regex isn't doing what you would want anyway. In particular, you need some quantifiers, or else your email addresses will only be able to consist of one character ahead of the #, and one after. And you need anchors at the beginning and end of the sequence so that you're matching against the entire address, not just the two characters closest to the #.
Consider this:
if( preg_match("^[a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+$", $email ) ) {
// Whatever
}
Keep in mind, however, that this is really a poor-man's approach to validating an email address. Email addresses can contain a lot more characters than those listed in the character class I provided. Furthermore, it would also be possible to construct an invalid email address with those same character classes. It doesn't even begin to deal with Unicode. Using a regex to validate an email address is quite difficult. Friedl takes a shot at it in Mastering Regular Expressions (O'Reilly), and his effort takes a 2KB regular expression pattern. At best, this is only a basic sanity check. It's not a secure means of verifying an email address. At worst, it literally misses valid regexes, and still matches invalid ones.
There is the mailparse_rfc822_parse_addresses function which is more reliable in detecting and matching email addresses.
You need to use preg_match to run the regular expression.
Now you're setting the $email = to the regular expression.
It could look like:
if ( preg_match("[a-zA-Z0-9]#[a-zA-Z0-9]", $email ))
Also keep in mind when matching in an if you must use the == operator.
I believe best pratice would be to use a filter_var instead like:
if( ! filter_var( $email , FILTER_VALIDATE_EMAIL )) {
// Failed.
}
Another way taken from: http://www.linuxjournal.com/article/9585
function check_email_address($email) {
// First, we check that there's one # symbol,
// and that the lengths are right.
if (!ereg("^[^#]{1,64}#[^#]{1,255}$", $email)) {
// Email invalid because wrong number of characters
// in one section or wrong number of # symbols.
return false;
}
// Split it into sections to make life easier
$email_array = explode("#", $email);
$local_array = explode(".", $email_array[0]);
for ($i = 0; $i < sizeof($local_array); $i++) {
if
(!ereg("^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-][A-Za-z0-9!#$%&
↪'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$",
$local_array[$i])) {
return false;
}
}
// Check if domain is IP. If not,
// it should be valid domain name
if (!ereg("^\[?[0-9\.]+\]?$", $email_array[1])) {
$domain_array = explode(".", $email_array[1]);
if (sizeof($domain_array) < 2) {
return false; // Not enough parts to domain
}
for ($i = 0; $i < sizeof($domain_array); $i++) {
if
(!ereg("^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|
↪([A-Za-z0-9]+))$",
$domain_array[$i])) {
return false;
}
}
}
return true;
}
I have an app that I'm developing, in it users can choose a name for themselves. I need to be able to filter out "bad" names, so I do this for now:
$error_count=0;
$bad_names="badname1badname2";
preg_match_all("/\b".$user_name."\b/i",$global['bad_names'],
$matches,PREG_OFFSET_CAPTURE);
if(count($matches[0])>0)
{
$error_count++;
}
This would tell me if the user's name was inside the bad names list, however, it doesn't tell me if the bad name itself is in the user's name. They could combine a bad word with something else and I wouldn't detect it.
What kind of regex (if I even use regex) would I use for this? I need to be able to take any bad name (preferably in an array like $bad_names), and search through the user's name to see whether that word is within their name. I'm not great with regex, and the only way I can think of is to put it all through a loop which seems highly inefficient. Anyone have a better idea? I guess I need to figure out how to search through a string with an array.
$badnames = array('name1', 'name2');
// you need to quote the names so they can be inserted into the
// regular expression safely
$badnames_quoted = array();
foreach ($badnames as $name) {
$badnames_quoted[] = preg_quote($name, '/');
}
// now construct a RE that will match any bad name
$badnames_re = '/\b('.implode('|', $badnames_quoted).')\b/Siu';
// no need to gather all matches, or even to see what matched
$hasbadname = preg_match($badnames_re, $thestring);
if ($hasbadname) {
// bad name found
}
private static $bad_name = array("word1", "word2", "word3");
private static $forbidden_name = array (array of unwanted character strings)
private static function userNameValid($name_in) {
$badFound = preg_match("/\b(" . implode(self::$bad_name,"|") . ")\b/i", $name_in); // checks array for exact match
$forbiddenFound = preg_match("/(" . implode(self::$forbidden_name,"|") . ")/i", $name_in); // checks array for any character match with a given name (i.e. "ass" would be found in assassin)
if ($badFound) {
return FALSE;
} elseif ($forbiddenFound) {
return FALSE;
} else {
return TRUE;
}
This works GREAT for me
I use the clas below to validate user input. Originally it was just a collection of static functions grouped together.
However, I modifed it to an object style and added in a private memeber to hold the user input array. What is the next step to making this class adaptable, i.e. more generic so that it can be used by others as part of a library?
$message is the text displayed to the user on a validation fail.
Library Code:
class validate
{
private $input;
function __construct($input_arg)
{
$this->input=$input_arg;
}
function empty_user($message)
{
if((int)!in_array('',$this->input,TRUE)) return 1;
echo $message;return 0;
}
function name($message)
{
if(preg_match('/^[a-zA-Z-\.]{1,40}$/',$this->input['name'])) return 1;
echo $message;return 0;
}
function email($message)
{
if(preg_match('/^[a-zA-Z0-9._s-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{1,4}$/',$this->input['email'])) return 1;
echo $message;return 0;
}
function pass($message)
{
if(preg_match('/^[a-zA-Z0-9!##$%^&*]{6,20}$/',$this->input['pass'])) return 1;
echo $message;return 0;
}
}
Application Code:
function __construct()
{
parent::__construct();
$obj=check_new($this->_protected_arr);
$a='<si_f>Please enter both an email and a password!';
$b='<si_f>Please enter a valid email!';
$c='<si_f>Please enter a valid password!';
if($obj->empty_user($a) && $obj->email($b) && $obj->pass($c) && self::validate())
{
self::activate_session();
echo "<si_p>";
}
}
I'd not write all these function in a generic class. I'd rather have separate functions that perform specific checks, and maybe a specific class that calls these checks on my specific input.
This class now echo's, which is never a good solution for a class like this. Just let it perform the check and raise an exception if something's wrong. If exceptions are too hard, or don't fit in your achitecture, let your function return false, and set a property that can be read afterwards.
About your specific checks:
Your e-mail check is very strict and doesn't allow all e-mail addresses. The domain, for instance, can be an IP address too, and the username (the part before the #) can include many obscure characters, including an #. Yes, really!
Why must a password be 6 characters at least? And why on earth would you limit the password to 20 characters? I use passwords of over 20 characters, and I know many other people that do too. Just let everybody type everything they want. Anything. Let them post 3MB of text if they like. Let them include unicode characters if they want. What is a better protection that having a bunch of chinese characters as a password? And if they want to enter just a, that's their responsibility too.
You should never ever store the password itself anyway, so just hash whatever they input and store the 32 characters that gives you (if you use MD5 hashing). The only password that you may refuse is an empty password. Anything else should go.
Same goes for name. 40 characters? Really. I can imagine people having names that long. Add a little more space. Bytes aren't that expensive, and it's not that you're gonna have 2 billion users.
Maybe it's worth having a look at Zend Validate? Or any other PHP frameworks validate classes. Just then extend them to add the functionality you want.
In answer to your question, is it worth having another variable in the class so you can check the error?
class validate
{
private $input;
public $error = false;
function __construct($input_arg)
{
$this->input=$input_arg;
}
function empty_user($message)
{
if((int)!in_array('',$this->input,TRUE)) return 1;
echo $message;$this->error = "Empty message";
}
... else
}
$validate = new validate($empty_message);
if( !$validate->empty_user('this input is empty') === false)
{
echo "Was not empty";
}