1
\$\begingroup\$

I have two access roles as of now for example account_type 1 and 2.

What I am doing is, account_type 1 can log in using mobile no and account_type 2 can log in with email and password.

Both scenarios are working with the below code but is this code is the best code or is this the right way to do? or can we reduce the code?

$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : ''; // getting from the login page

switch ($action) {
/*there are many cases here*/
case 'login' : login($pdo); break;

default : header('Location: index.php'); 
}




function login($pdo){
  $account_type=sanitize_data($_POST['account_type']);
  $mobileno =sanitize_data($_POST['mobileno']);
  $email=$_POST['email'];
  $password =sanitize_data($_POST['password']);
 

if (empty($account_type)) {
   $_SESSION['error']=  "Please select account type";
   header('location:../login');
 }


 elseif($account_type==1){


          $_SESSION['account_type']='1';
          if(empty($mobileno)){
            $_SESSION['error']="Please enter the mobile no.";
            header('location:../login');
          }
          elseif(!is_numeric($mobileno))
            {
             $_SESSION['error']="Please enter number only.";
             header('location:../login');
            }
          elseif(strlen($mobileno)!=10)
            {
             $_SESSION['error']="Please enter 10 digits.";
             header('location:../login');
            }
            elseif(!preg_match('/^\d{10}$/',$mobileno)){
              $_SESSION['error']="You did not enter a valid number";
              header('location:../login');
            }

            else{
                try {
                 
                  $sql="SELECT reg_id, mobileno,account_type FROM tbl_register WHERE  mobileno=:mobileno and is_active=1";
                  $stmt= $pdo->prepare($sql);
                  $stmt->bindParam(':mobileno', $mobileno);
                  $stmt->execute();
                  $result = $stmt->fetch();
                  $countrow= $stmt->rowCount();

                     if (($countrow) > 0) {
                       $_SESSION['reg_id']=$result['reg_id'];
                       $_SESSION['mobileno']=$result['mobileno'];
                       $_SESSION['role']=$result['account_type'];
                       header("Location:../buyer-dashboard.php");
                     }
                     else{
                       $_SESSION['error']="Mobile no does not match";
                        header('location:../login');
                     }

                    
                  } catch (Exception $e) {
                    print "Error!: " . $e->getMessage() . "</br>"; 
                    
                  }
              }

  }
else{

if($account_type==2){

    $_SESSION['account_type']='2';
        if(empty($email)){
            $_SESSION['error']="You did not enter a email.";
            header('location:../login');
          } //check for valid email 
         elseif(filter_var($email, FILTER_VALIDATE_EMAIL) === false){
          $_SESSION['error']= "You did not enter a valid email.";
          header('location:../login');
          }
          elseif( empty($password)) {
          $_SESSION['error']= "Please enter the password";
          header('location:../login');
           }
           else{

              try{ 

                    $sql="SELECT email,password,reg_id,account_type FROM tbl_register WHERE  email=:email and is_active=1";
                    $stmt= $pdo->prepare($sql);
                    $stmt->bindParam(':email', $email);
                    $stmt->execute();
                    $result = $stmt->fetch();
                     $countrow= $stmt->rowCount();
                     if (($countrow) > 0) {
                        if (password_verify($password, $result['password'])) {
                            $_SESSION['email']=$result['email'];
                            $_SESSION['reg_id']=$result['reg_id'];
                            $_SESSION['role']=$result['account_type'];
                            header("Location:/seller-dashboard.php");

                         }
                        else{
                          $errorMsg="Email & Password does not match";
                          header('location:../login');
                        }
                    }
                    else{
                         $errorMsg="This username is not register with us";
                          header('location:../login');
                    }
                      } catch(PDOExecption $e) { 
                            print "Error!: " . $e->getMessage() . "</br>"; 
                    }

           }

     }
    



}
  
}  



function sanitize_data($data)
{
$data = trim($data);
$data = stripslashes($data);
$data = strip_tags($data);
$data = htmlspecialchars($data);
return $data;    
}

Would you help me out with this issue?

\$\endgroup\$
8
  • \$\begingroup\$ Please fix your indentation. \$\endgroup\$
    – BCdotWEB
    Apr 13, 2021 at 12:15
  • \$\begingroup\$ @BCdotWEB, Sorry I haven't understood your point. Can you explain in detail? \$\endgroup\$ Apr 13, 2021 at 12:18
  • \$\begingroup\$ The indentation of your code is inconsistent and all over the place. Please fix it. Use your IDE or use a site like tutorialspoint.com/online_php_formatter.htm . Badly formatted code is likely to get no review. \$\endgroup\$
    – BCdotWEB
    Apr 13, 2021 at 13:39
  • \$\begingroup\$ @BCdotWEB, Thanks for the explanation. Can you help me with the code? or any link where I can read it? \$\endgroup\$ Apr 13, 2021 at 13:57
  • \$\begingroup\$ @BCdotWEB, I used the above link and beautify the code. \$\endgroup\$ Apr 13, 2021 at 14:01

3 Answers 3

3
\$\begingroup\$

From the top as I read down your script:

  • $account_type is perhaps too generalized, it might be more indicative (and I prefer camelCasing variables) to use $access_mode because in the future you might need to expand on the different types of accounts you have and those different types may be permitted differing access modes.

  • I never use $_REQUEST because I always design a singular submission method to any form/action. You don't appear to be honoring multiple submission methods here, so only use $_POST. Furthermore, you are correct in using $_POST because the script to be executed is "writing" to the session.

  • You can avoid the first line of code by using a null coalescing operator in the switch.
    switch ($_POST['action'] ?? '') {

  • I have a general dislike for switch blocks, specifically because they are so verbose, however they are appropriate for making multiple checks on a value. I'll urge you not to try to "save lines" by writing the case, the body, and the break on one line. Let your code breathe and practice proper indentation.

  • Calling isset() or empty() AFTER you perform any operation on the variable (e.g. sanitize_data()) is an inappropriate technique. If the variable is undeclared, then php will bark at you for trying to access it. If it is guaranteed to exist before isset() or empty(), then just write a null or a falsey check on the variable.

  • I see that the login() function is unconditionally sanitizing three of the four user-supplied values. However, I don't believe any sanitization is warranted. The account type must be an integer, this is probably not a free-text field in your form to begin with. Don't bother sanitizing it, just use another null coalesced switch block and if no case is matched, then reroute the user and exit(). Okay, I'll grant you that phone numbers might be reasonably sanitized, but this is a much simpler/deliberate action - preg_replace('~\D+~', '', $_POST['mobileno']). There is no need for the battery of sanitizing functions. PASSWORDS MUST NEVER BE SANITIZED ...EVER - if the user wants their password to contain an html tag, it is NOT your place to purge it from the string. And finally, you should only sanitize the variables that you intend to use.

  • If you insist on validating the phone number, is_numeric() can possibly allow an invalid string (negative number or scientific notation). I recommend null coalescing the value with an empty string and checking it with ctype_digit(). Your client-side validation should be doing the same style check. If the value is missing or invalid, then offer just one blanket response - Missing/Invalid mobile number. That said, I do not recommend the php-level validation -- just let sql do that check for you.

  • Your db query is secure/stable because you are using a prepared statement properly. I don't understand why account_type is returned in the result set. I believe AND account_type = 1 should be instead appended to the WHERE clause.

  • $rowcount is a single-use variable. This is unnecessary storage; just feed the returned value of rowCount() directly to the if.

  • Mobile-only account access is INCREDIBLY insecure. Any malicious attacker can infiltrate you login-"protected" site by guessing a 10-digit number. You need to institute an addition identifier -- even if it is a 4-digit pin, or company name, or something ...anything.

  • You should definitely not be printing raw thrown exception errors to the public.

  • There is no reason to include a column in the result set if it is a column in your WHERE clause -- think about it, you are already guaranteeing what the value is so you don't need to return it.

  • I recommend that you not retain personally identifying data in a session. Session hijacking is a thing. Ask yourself if you really need the email to kept in the session -- you probably don't, you can probably afford to use the user's id in the session and use that id to fetch the email if/when you actually need it.

Your snippet might resemble this:

switch ($_POST['action'] ?? '') {
    case 'login':
        login($pdo);
        break;
    default:
        redirectAndExit('Location: index.php');
}

function login(PDO $pdo)/* : never */ {
    // account types: 1 = buyer, 2 = seller, can one account be both a buyer and a seller?
    switch ($_POST['account_type'] ?? 0) {
        case '1':
            if (!preg_match('~^\d{10}$~', $_POST['mobileno'] ?? '')) {
                $_SESSION['error'] = 'Missing/Invalid mobile number';
                redirectAndExit('location:../login');
            }
            $sql = "SELECT reg_id
                    FROM tbl_register
                    WHERE mobileno=?
                      AND is_active=1
                      AND account_type='1'";
            $stmt = $pdo->prepare($sql);
            $stmt->execute([$_POST['mobileno']]);
            $regId = $stmt->fetchColumn();
            if (!$regId) {
                $_SESSION['error'] = 'Failed to login via mobile number';
                redirectAndExit('location:../login');
            }
            $_SESSION['account_type'] = 1;
            $_SESSION['reg_id'] = $regId;
            $_SESSION['mobileno'] = $_POST['mobileno'];
            redirectAndExit('Location:../buyer-dashboard.php');
        break;
    case 2:
        if (!filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL)) {
            $_SESSION['error'] = 'Missing/Invalid email address';
            redirectAndExit('location:../login');
        } elseif (empty($_POST['password'])) {
            $_SESSION['error'] = 'Missing password';
            redirectAndExit('location:../login');
        }
        $sql = "SELECT password,reg_id
                FROM tbl_register
                WHERE email=?
                  AND is_active=1
                  AND account_type=2";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([$_POST['email']]);
        if (!$stmt->rowCount()) {
            $_SESSION['error'] = 'Failed to login via email & password';
            redirectAndExit('location:../login');
        }
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!password_verify($password, $result['password'])) {
            $_SESSION['error'] = 'Failed to login via email & password';
            redirectAndExit('location:../login');
        }
        $_SESSION['reg_id'] = $result['reg_id'];
        $_SESSION['role'] = '2';
        redirectAndExit("Location:/seller-dashboard.php");
    break;
    default:
        $_SESSION['error'] = 'Unexpected submission';
        redirectAndExit('location:../login');
}

function redirectAndExit(string $newLocation)/* : never */ {
    header($newLocation);
    exit();
}

...hmm, the second switch block is a little too bloated for my taste. You might like to split it into individual functions based on the account_type. The first switch block can do these conditional function calls.


Follow up questions from the OP:

  1. I have to call $_POST['mobileno'] instead of $mobileno in the execute, right?

    • Correct, this was an oversight when I was rewriting your script. I have now updated my snippet. If you are going to mutate the submission in any way (e.g. trim()), then I endorse declaring $mobileNo so that there is a distinction between the two potentially different strings.
  2. Why use written /* : never */ ?

  3. Why removed try and catch block?

  4. I have doubt in point 5. I thought sanitize_data() is good for SQL injection.

    • I fully support validating data on the way in. Your client-side form fields should be halting the submission data for the best UX. If that is all in place, then you can unapologetically block whole submissions that are not 100% correct. With these tight rules, you might trim() non-password values, but that's about it. You should ONLY be calling htmlspecialchars() just before printing data into an html document. If a user's valid email address is "call_me_<s>x</s>"@example.com then you will damage the data. If a username or password includes <s>x</s> then allow it. You will NEVER print the password onto an html document. As for the username, don't ever print it as rendered text (don't show x).
  5. DO I need to use like this ctype_digit($_POST['mobileno'])? If yes, then I believe that ctype_digit() will accept the value like in single or double quote ('1234567890') not like 1234567890.

    • ctype_ functions require that the the input is string typed. If this input is coming from an input field, it will be a string typed. If for some reason the variable is not a string, you can easily cast it
\$\endgroup\$
1
  • \$\begingroup\$ I apologize for the late reply. I tried each point and implemented it with my code and It's working. I have some doubts. 1) I have to call $_POST['mobileno'] instead of $mobileno in the execute. right? 2) why use written /* : never */ ? 3) Why removed try and catch block? 4) I have doubt in point 5. I thought sanitize_data() is good for SQL injection. 5) DO I need to use like this ctype_digit($_POST['mobileno'])? If yes then I believe that ctype_digit() will accept the value like in single or double quote ('1234567890') not like 1234567890 \$\endgroup\$ Apr 17, 2021 at 3:48
0
\$\begingroup\$

Few obvious issues in logic:

  1. You are just getting mobile number, but not validating it with an OTP or any password associated with it! This makes anyone can login with any mobile number.

  2. Too many error messages like, enter mobile number, enter 10 digits, enter valid number. This could be handled via front-end validation for entering only allowed inputs. And error message can be made generic as "Enter valid mobile number!". Example 999-999-999 is same as 999999999.

  3. Account type 2 is checked inside else block. I suppose this piece of logic can be made as another elseif of main if block.

  4. Code indentation. It's very difficult to read the code with current formatting.

  5. Logic to validate mobileno is very difficult to understand, let alone validate! Use a helper method to validate mobileno and return boolean value.

\$\endgroup\$
2
  • \$\begingroup\$ 1) Yes, as of now, I am directly giving access to log in. No OTP, No Password. 2) Yes, I am using the front-end validation but if the script stops then? So I am using server-side validation. 3) If I use else if then what should I use for the else part? 4) Now I updated the code formatted. 5) Can you help me with example? or any link? \$\endgroup\$ Apr 13, 2021 at 14:09
  • 3
    \$\begingroup\$ @Gok Client-side validation is for a better UX. Server-side validation is for security. The former is important, but the latter is absolutely essential. \$\endgroup\$ Apr 13, 2021 at 21:58
-1
\$\begingroup\$

Here's a way to do it:

small security issue (minor nitpicking point so don't fret about it too much)

  1. super-globals are the least safe variable so you should be as specific as possible when choosing which to use - and I'm assuming your are using $_POST to pass on variables from form to code so you should use $_POST to test as well

  2. you don't need to specify the boolean action in a separate line so you initial check could look like this instead

     if ($_POST['action']) {
         // rest of code here
     }
    

next minor nitpicking issue (again don't sweat to much about it) - avoid switch-statements like the plague and 'switch' to if-statements instead

  1. switch-statements quickly becomes hard to read/understand as they get longer (for anyone not you that later have to look at and maybe change the code)

  2. if-statements read like normal language making for easier read/understanding of code for others later (ie. if employee is stealing fire employee) even a noob will understand this so the next code becomes

     if ($_POST(['action']) === 'login') {
         login($pdo);
     } elseif ('something else') {
         // do something else
     } // etc {
     } else {
         // throw error-statement
         header('Location: index.php'); 
     }
    

a more serious security point is when cleaning variables/arrays there is a order of operations

  1. sanitize
  2. validate
  3. escape
  4. (if possible) preg_match

Do all of these and do not change the order of these - and different types (ie. string, number, email, etc.) require different ways of sanitizing and validating
So at the level you are cleaning here you should make sanitize_data into cleanInteger + cleanEmail + cleanString, etc.) and switch to using the appropriate filters for each type

So your sanitize_data() function becomes

function cleanInteger($data) {
    $data = trim($data);
    $data = filter_var($data, FILTER_SANITIZE_NUMBER_INT);
    $data = filter_var($data, FILTER_VALIDATE_INT);
    $data = htmlspecialchars($data);
    return $data;    
}

function cleanEmail($data) {
    $data = trim($data);
    $data = filter_var($data, FILTER_SANITIZE_EMAIL);
    $data = filter_var($data, FILTER_VALIDATE_EMAIL);
    $data = htmlspecialchars($data);
    return $data;    
}

function cleanString($data) {
    $data = trim($data);
    $data = filter_var($data, FILTER_SANITIZE_STRING);
    $data = htmlspecialchars($data);
    return $data;    
}

Now to your login function:

function login($pdo) {
    // first set you variables
    // no need to clean here
    // as you are only using them for comparison
    // in the error handling
    // and you only need to preg_match the mobile no. for that
    
    $account_type = $_POST['account_type'];
    // only accepts the result if it's a 10-digit number
    $mobileno = preg_match('/^\d{10}$/', $_POST['mobileno']) ? $_POST['mobileno'] : NULL;
    $email = $_POST['email']);
    $password = $_POST['password']);
    
    // then clear out your session cookies
    // so you won't have any leftover error messages floating around
    // and you are always getting the resent error messages
    if ($_SESSION['error']) {
        unset($_SESSION['error']);
    }
    
    // then you error handle and no need to check for empty() 
    // when !variable will do
    // and always remember to exit function
    // as there is no need for the users computer or your server
    // to spend more time and resources running code if the checks fails
    if (!$account_type) {
        $_SESSION['error'] = "Please select account type";
        header('location:../login');
        exit;
    } elseif ($account_type === 1) {
        // no need to run any more checks
        // as if it passes (doesn't exist)
        // then it wasn't a 10-digit number using (0-9)
        if (!$mobileno) {
            $_SESSION['error'] = "Please input valid mobile no., mobile no. can only contain the numbers 0-9 and have to be 10 digits";
            header('location:../login');
            exit;
        } else {
            // you try to login
            // first you test if mobile no. exists
            try {
                // always make the code as readable as possible = cleaner code
                $sql="
                    SELECT
                        reg_id, mobileno, account_type, password // and get password for comparison to input later
                    FROM
                        tbl_register
                    WHERE
                    mobileno = :mobileno AND is_active = 1
                    ";
                $stmt= $pdo->prepare($sql);
                // using named variables using bindParam
                // you should always be as specific as possible
                // using appropriate parameters and length of expected variable
                $stmt->bindParam(':mobileno', $mobileno, PDO::PARAM_INT, 10);
                $stmt->execute();
                $result = $stmt->fetch();
                // as you are not using the count for anything like a loop
                // there is no need for it
                // just check if $result has a value
            }  catch (Exception $e) {
                // never print or echo or ... the $e error message
                // as it hold valuable database info
                // that a hacker can use
                // instead write it to a text-file
                // you keep above your root/html/public_html-directory
                // so only you can read
                file_put_contents("../error/e.txt", $e->getMessage(), FILE_APPEND);
            }
            if (!$result) {
                // here you should never be specific as it will help a hacker
                $_SESSION['error']="Mobile no and/or password does not match";
                header('location:../login');
                exit;
            } else {
                // then you verify the password
                
                // for this you should you should use whatever method
                // you used to hash the user when they were created in the first place
                // and if you are not hashing but storing passwords in plain text
                // you have way bigger security issues than this script
                
                // but if not already using the password_hash function
                // you should look into it
                // and then your hashing (and later password_verify)
                // would look like this
                
                // first set the database password hash into a variable
                $hash = $result['password'];
                
                // then add a cost and use PASSWORD_DEFAULT for hashing
                $options = [
                    'cost' => 10
                }
                if (!password_verify($password, $hash, PASSWORD_DEFAULT, $options)) {
                    // here again you should never be specific as it will help a hacker
                    $_SESSION['error']="Mobile no and/or password does not match";
                    header('location:../login');
                    exit;
                } else {
                    // now check if updates have been made
                    // to the default hash-algorithm
                    // or the options have changed since last time
                    // this has the added benefit
                    // that even if you so far havent used any cost
                    // or used PASSWORD_DEFAULT
                    // this will update all your user password hashes for you
                    // automatically every time the user logs in
                    // so if you use this login code
                    // your users passwords are now as secure as can be
                    
                    if (password_needs_rehash($hash, PASSWORD_DEFAULT, $options)) {
                        $newHash = password_hash($password, PASSWORD_DEFAULT, $options);
                        try {
                            $sql = "
                                UPDATE
                                    tbl_register
                                SET
                                    password = :newpassword
                                WHERE
                                    password = :oldpassword
                            ";
                            $stmt= $pdo->prepare($sql);
                            $stmt->bindParam(':newpassword', $newHash, PDO::PARAM_STR);
                            $stmt->bindParam(':oldpassword', $hash, PDO::PARAM_STR);
                            $stmt->execute();
                        } catch (Exception $e) {
                            file_put_contents("../error/e.txt", $e->getMessage(), FILE_APPEND);
                        }
                    } 
                    
                    // now and ONLY now do you clean and preg_match the rest
                    // just before it hits the webpage to be used
                    
                    // except mobile no. as it was already preg_matched
                    // and the value in the database matched
                    $_SESSION['reg_id'] = preg_match('/^[0-9]+$/', $result['reg_id']) ? cleanInteger($result['reg_id']) : NULL;
                    $_SESSION['mobileno'] = cleanInteger($result['mobileno']);
                    $_SESSION['role'] = preg_match('/^[1-2]{1}$/', $result['account_type']) ? cleanInteger($result['account_type']) : NULL;
                    header("Location:../buyer-dashboard.php");
                }
            }
        } elseif ($account_type === 2) {
            // do the same as above just with email instead of mobile no.
            // as for cleaning and preg_matching results
            // no need to preg_match email
            // as FILTER_SANITIZE_EMAIL and FILTER_VALIDATE_EMAIL
            // does that for you
            // and just copy the clean and preg_match from above for the other 2
            $_SESSION['email'] = cleanEmail($result['email']); 
        // if $account_type is niether 1 or 2
        } else {
            $_SESSION['error'] = "Please chose a valid account type, account type can only be the numbers 1 or 2";
        }
    }
}

So your final code should look like this:

function cleanInteger($data) {
    $data = trim($data);
    $data = filter_var($data, FILTER_SANITIZE_NUMBER_INT);
    $data = filter_var($data, FILTER_VALIDATE_INT);
    $data = htmlspecialchars($data);
    return $data;    
}

function cleanEmail($data) {
    $data = trim($data);
    $data = filter_var($data, FILTER_SANITIZE_EMAIL);
    $data = filter_var($data, FILTER_VALIDATE_EMAIL);
    $data = htmlspecialchars($data);
    return $data;    
}

function cleanString($data) {
    $data = trim($data);
    $data = filter_var($data, FILTER_SANITIZE_STRING);
    $data = htmlspecialchars($data);
    return $data;    
}

function login($pdo) {
    $account_type = $_POST['account_type'];
    $mobileno = preg_match('/^\d{10}$/', $_POST['mobileno']) ? $_POST['mobileno'] : NULL;
    $email = $_POST['email']);
    $password = $_POST['password']);
    
    if ($_SESSION['error']) {
        unset($_SESSION['error']);
    }
    
    if (!$account_type) {
        $_SESSION['error'] = "Please select account type, account type can only be the numbers 1 or 2";
        header('location:../login');
        exit;
    } elseif ($account_type === 1) {
        if (!$mobileno) {
            $_SESSION['error'] = "Please input valid mobile no., mobile no. can only contain the numbers 0-9 and have to be 10 digits";
            header('location:../login');
            exit;
        } else {
            try {
                $sql="
                    SELECT
                        reg_id, mobileno, account_type, password // and get password for comparison to input later
                    FROM
                        tbl_register
                    WHERE
                    mobileno = :mobileno AND is_active = 1
                    ";
                $stmt= $pdo->prepare($sql);
                $stmt->bindParam(':mobileno', $mobileno, PDO::PARAM_INT, 10);
                $stmt->execute();
                $result = $stmt->fetch();
            }  catch (Exception $e) {
                file_put_contents("../error/e.txt", $e->getMessage(), FILE_APPEND);
            }
            if (!$result) {
                $_SESSION['error']="Mobile no and/or password does not match";
                header('location:../login');
                exit;
            } else {
                $hash = $result['password'];
                
                $options = [
                    'cost' => 10
                }
                if (!password_verify($password, $hash, PASSWORD_DEFAULT, $options)) {
                    $_SESSION['error']="Mobile no and/or password does not match";
                    header('location:../login');
                    exit;
                } else {
                    if (password_needs_rehash($hash, PASSWORD_DEFAULT, $options)) {
                        $newHash = password_hash($password, PASSWORD_DEFAULT, $options);
                        try {
                            $sql = "
                                UPDATE
                                    tbl_register
                                SET
                                    password = :newpassword
                                WHERE
                                    password = :oldpassword
                            ";
                            $stmt= $pdo->prepare($sql);
                            $stmt->bindParam(':newpassword', $newHash, PDO::PARAM_STR);
                            $stmt->bindParam(':oldpassword', $hash, PDO::PARAM_STR);
                            $stmt->execute();
                        } catch (Exception $e) {
                            file_put_contents("../error/e.txt", $e->getMessage(), FILE_APPEND);
                        }
                    } 
                    
                    $_SESSION['reg_id'] = preg_match('/^[0-9]+$/', $result['reg_id']) ? cleanInteger($result['reg_id']) : NULL;
                    $_SESSION['mobileno'] = cleanInteger($result['mobileno']);
                    $_SESSION['role'] = preg_match('/^[1-2]{1}$/', $result['account_type']) ? cleanInteger($result['account_type']) : NULL;
                    header("Location:../buyer-dashboard.php");
                }
            }
        } elseif ($account_type === 2) {
            // do the same as above just with email instead of mobile no.
            $_SESSION['email'] = cleanEmail($result['email']); 
        } else {
            $_SESSION['error'] = "Please chose a valid account type, account type can only be the numbers 1 or 2";
        }
    }
}

if ($_POST['action']) {
    if ($_POST(['action']) === 'login') {
        login($pdo);
    } elseif ('something else') {
        // do something else
    } // etc {
    } else {
        // throw error-statement
        header('Location: index.php'); 
    }
}
\$\endgroup\$
12
  • \$\begingroup\$ if ($_POST['action']) { this is not good enough if this script will be run without receiving that superglobal element. switch() is most appropriate when checking the same data for different values. Please read stackoverflow.com/a/4882317/2943403 $data = filter_var($data, FILTER_SANITIZE_EMAIL); $data = filter_var($data, FILTER_VALIDATE_EMAIL); looks like a typo, but frankly I don't support any of those sanitization functions. There is no benefit in wrapping \d in a character class. \$\endgroup\$ Apr 14, 2021 at 6:56
  • \$\begingroup\$ Those preg_match() calls have their parameters in the wrong order. I am confident that YourCommonSense will flame you for manually logging thrown exceptions. preg_match('~^[1-2]{1}$~', ...)` is working too hard and using suboptimal pattern syntax, it could be ~^[12]$~', but why not in_array(..., [1, 2])`? There is just so much that I do not like about your review versus any redeeming advice, for that reason I must downvote and advise the OP to not implement most of your suggestions. \$\endgroup\$ Apr 14, 2021 at 7:00
  • \$\begingroup\$ @mickmackusa mofo... thank you... changed it to correct order... \$\endgroup\$
    – thothlike
    Apr 14, 2021 at 7:10
  • \$\begingroup\$ @mickmackusa for the rest we will just agree to disagree and downvoting is your prerogative... so no problem there \$\endgroup\$
    – thothlike
    Apr 14, 2021 at 7:12
  • \$\begingroup\$ This is also wrong: $mobileno = preg_match('/^[\d]{10}$/', $_POST['mobileno']); and $_SESSION['reg_id'] = preg_match('/^[0-9]+$/', cleanInteger($result['reg_id'])); and $_SESSION['role'] = preg_match('/^[1-2]{1}$/', cleanInteger($result['account_type']));. I assume that you read the earlier reviews before posting your review and that you do not agree with other advices where your review is in conflict. Is this correct? \$\endgroup\$ Apr 14, 2021 at 7:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.