-4

This is jslogin.php

<?php
error_reporting(-1);
session_start();
require_once('config.php');


$email = $_POST['email'];
$username = $_POST['username'];
$password = $_POST['password'];

$isValid = true;
if (empty($password)) {
    echo 'You need to enter a Password';
    $isValid = false;
}

if (empty($username)) {
    echo 'You need to enter a Username';
    $isValid = false;
}

if (empty($email)) {
    echo 'You need to enter a Email Address';
    $isValid = false;
}elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "You need to have a valid Email Address";
    $isValid = false;
}

if ($isValid) {
    $sql = "SELECT * FROM accounts WHERE username=? and password=? and email=? LIMIT 1";
    $stmtselect = $db->prepare($sql);
    $result = $stmtselect->execute([$username, $password, $email]);
    $user = $stmtselect->fetch(PDO::FETCH_ASSOC);
    if ($stmtselect->rowCount() > 0) {
        $_SESSION['accounts'] = $user;
        echo 'You have signed in successfully!';
    } else {
        echo 'Incorrect Username or Password or Email';
    }
}

This is login.php

<?php 
error_reporting(-1);
    session_start();
    
if(isset($_SESSION['hello_world_accounts'])){
    header("Location: index.php");
}

?>
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Programming Knowledge Login</title>
    <link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="css/styles.css">
</head>
<body>
<div class="container h-100">
    <div class="d-flex justify-content-center h-100">
        <div class="user_card">
            <div class="d-flex justify-content-center">
                <div class="brand_logo_container">
                    <img src="img/logo.png" class="brand_logo" alt="Programming Knowledge logo">
                </div>
            </div>  
            <div class="d-flex justify-content-center form_container">
                <form method="post">
                    <div class="input-group mb-2">
                        <div class="input-group-append">
                            <span class="input-group-text"><em class="fas fa-user"></em></span>                 
                        </div>
                        <input type="text" name="username" id="username" class="form-control input_user" placeholder="Username" required>
                    </div>
                    <div class="input-group mb-2">
                        <div class="input-group-append">
                            <span class="input-group-text"><em class="fas fa-key"></em></span>                  
                        </div>
                        <input type="password" name="password" id="password" class="form-control input_pass" placeholder="Password" required>
                    </div>
                    <div class="input-group mb-1">
                        <div class="input-group-append">
                            <span class="input-group-text"><em class="fas fa-inbox"></em></span>                    
                        </div>
                        <input type="email" name="email" id="email" class="form-control input_pass" placeholder="Email" required>
                    </div>
                    <div class="form-group">
                        <div class="custom-control custom-checkbox">
                            <input type="checkbox" name="rememberme" class="custom-control-input" id="customControlInline">
                            <label class="custom-control-label" for="customControlInline">Remember me</label>
                        </div>
                    </div>
                
            </div>
            <div class="d-flex justify-content-center mt-1 login_container">
                <button type="button" name="button" id="login" class="btn login_btn">Login</button> 
            </div>
            </form>
            <div class="mt-3 mb-1">
                <div class="d-flex justify-content-center links">
                    Don't have an account? <a href="registration.php" class="ml-2">Sign Up</a>
                </div>
                <div class="d-flex justify-content-center">
                    <a href="#">Forgot your password?</a>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="http://code.jquery.com/jquery-3.3.1.min.js"
              integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
              crossorigin="anonymous"></script>
<script type="text/javascript" src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script>
    $(function(){
        $('#login').click(function(e){

            var valid = this.form.checkValidity();

            if(valid){
                var username = $('#username').val();
                var password = $('#password').val();
                var email = $('#email').val();
            }

            e.preventDefault();

            $.ajax({
                type: 'POST',
                url: 'jslogin.php',
                data:  {username: username, password: password, email: email},
                success: function(data){
                    alert(data);
                    if($.trim(data) === "1"){
                        setTimeout(' window.location.href =  "index.php"', 1000);
                    }
                },
                error: function(data){
                    alert('There were errors while doing the operation.');
                }
            });

        });
    });
</script>
</body>
</html>

This is congfig.php

<?php

error_reporting(-1);
$db_user = "root";
$db_pass = "";
$db_name = "hello_world_accounts";

$db = new PDO('mysql:host=localhost;dbname='. $db_name . ';charset=utf8', $db_user, $db_pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

This is index.php

<?php 

error_reporting(-1);
session_start();

    if(!isset($_SESSION['hello_world_accounts'])){
        header("Location: login.php");
    }

    if(isset($_GET['logout'])){
        session_destroy();
        unset($_SESSION);
        header("Location: login.php");
    }

?>
<!DOCTYPE>
<html lang="en">
<head>
<title>Welcome</title>
</head>
<body>
<p>Welcome to index</p>


<a href="index.php?logout=true">Logout</a>
</body>
</html>

everytime i put in my email but not my username and password it says i need to put all three in even when one is already in why is this happening and how do I fix it? I thought about priorities but I don't know how or what to do that...

the rest of the code on the page is as follows

Please don't say anything about having the password as plain text.

Here is my test mysql. My Test MYSQL Here is my test website. My Test Website

  • `!stripos` is incorrect. It should be `!== FALSE` That also is not how should validate an email address – user3783243 Mar 05 '21 at 18:05
  • You have a lot of nested if/elses that aren't necessary. I would suggest changing all that to else if instead – aynber Mar 05 '21 at 18:07
  • @user3783243 I tried to do ! == FALSE saying there was a error and nothing would work. I did !stripos and my messages were displaying. It started going wrong when I did if it is equal to '' –  Mar 05 '21 at 18:07
  • Need more information than that. Also sample strings would also help the question. – user3783243 Mar 05 '21 at 18:09
  • Also, that wouldn't be the proper way to check for an empty variable. You can try [empty](https://www.php.net/manual/en/function.empty.php) or [strlen](https://www.php.net/manual/en/function.strlen) is 0 – aynber Mar 05 '21 at 18:09
  • 1
    Another point of improvement: with the current structure, you would only display one error to the user even if there were multiple. That way, after correcting the error and submitting again, the user would be presented with the next error and then repeat the process... As a user, I'd expect a form to tell me all of the errors at once. Consider sending an array of error messages. – El_Vanja Mar 05 '21 at 18:13
  • 1
    Please never develop with `error_reporting(0);`, you are asking for trouble right from the start. On production, that's a different story, but never during dev. – Chris Haas Mar 05 '21 at 18:14
  • https://stackoverflow.com/questions/12026842/how-to-validate-an-email-address-in-php That will get rid of three of your conditionals Additionallty I would put the validation checks before the SQL, and looks like you have 3-5 extra `}`s at the end – user3783243 Mar 05 '21 at 18:14
  • @user3783243 I am using a text editor and it tells me what I need to do. I have the right amount of } and { –  Mar 05 '21 at 18:21
  • @ChrisHaas when I do this If I put a password and nothing else it says that I need to enter a password when I did. Same problem. –  Mar 05 '21 at 18:31

1 Answers1

2

Here's your original code when run through a formatter. You should notice, as people have pointed out, it is indented like crazy and has a lot of nesting. You are also querying the database on each request, even if the data is invalid.

$username = $_POST['username'];
$password = $_POST['password'];
$email = $_POST['email'];
$valid = "You need to have a valid Email Address";

$sql = "SELECT * FROM accounts WHERE username=? and password=? and email=? LIMIT 1";
$stmtselect  = $db->prepare($sql);
$result = $stmtselect->execute([$username, $password, $email]);

if (stripos($password, '')) {
    echo 'You need to enter a Password';
} else {
    if (stripos($username, '')) {
        echo 'You need to enter a Username';
    } else {
        if (stripos($email, '')) {
            echo 'You need to enter a Email Address';
        } else {
            if (!stripos($email, '@')) {
                echo $valid;
            } else {
                if (!stripos($email, '.')) {
                    echo $valid;
                } else {
                    if (!stripos($email, 'com')) {
                        echo $valid;
                    } else {
                        if ($result) {
                            $user = $stmtselect->fetch(PDO::FETCH_ASSOC);
                            if ($stmtselect->rowCount() > 0) {
                                $_SESSION['accounts'] = $user;
                                echo 'You have signed in successfully!';
                            } else {
                                echo 'Incorrect Username or Password or Email';
                            }
                        } else {
                            echo 'There were errors while connecting to database.';
                        }
                    }
                }
            }
        }
    }
}

Instead, here's a quick attempt at cleaning it up. The major changes are the switch to empty() checks, the usage of elseif, a better email address validator and moving the query to the final else clause.

$username = $_POST['username'];
$password = $_POST['password'];
$email = $_POST['email'];

if (empty($password)) {
    echo 'You need to enter a Password';
} elseif (empty($username)) {
    echo 'You need to enter a Username';
} elseif (empty($email)) {
    echo 'You need to enter a Email Address';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "You need to have a valid Email Address";
} else {
    $sql = "SELECT * FROM accounts WHERE username=? and password=? and email=? LIMIT 1";
    $stmtselect = $db->prepare($sql);
    $result = $stmtselect->execute([$username, $password, $email]);
    $user = $stmtselect->fetch(PDO::FETCH_ASSOC);
    if ($stmtselect->rowCount() > 0) {
        $_SESSION['accounts'] = $user;
        echo 'You have signed in successfully!';
    } else {
        echo 'Incorrect Username or Password or Email';
    }
}

EDIT

If your intention is to show multiple error messages and not just stop at the first one (as your original code does), then you can use multiple if blocks. Most people would collect the error messages in an array but I'll leave that up to you.

$isValid = true;
if (empty($password)) {
    echo 'You need to enter a Password';
    $isValid = false;
}

if (empty($username)) {
    echo 'You need to enter a Username';
    $isValid = false;
}

if (empty($email)) {
    echo 'You need to enter a Email Address';
    $isValid = false;
}elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "You need to have a valid Email Address";
    $isValid = false;
}

if ($isValid) {
    $sql = "SELECT * FROM accounts WHERE username=? and password=? and email=? LIMIT 1";
    $stmtselect = $db->prepare($sql);
    $result = $stmtselect->execute([$username, $password, $email]);
    $user = $stmtselect->fetch(PDO::FETCH_ASSOC);
    if ($stmtselect->rowCount() > 0) {
        $_SESSION['accounts'] = $user;
        echo 'You have signed in successfully!';
    } else {
        echo 'Incorrect Username or Password or Email';
    }
}

EDIT

If you don't provide a method on the <form> it defaults to GET. Your code is expecting it to be POST, however. Change the form to <form method="post">.

EDIT

I'm not going to use any of your HTML and instead I'm going to just make a very simple form that POSTs to itself. This is a very common first task you learn when programming in any web language. This page, by itself, ignoring your database, styling and JS logic should work 100% by itself. Once you've proven that you can start enhancing it with sessions and then maybe AJAX. But start simple.

The form doesn't include normal settings like required or optimal types on fields intentionally because I'm just trying to keep it as simple as possible.

I did add in the errors array which removes the need for $isValid because we can now check to see if the error has anything inside of it.

Please try this code all by itself, and once you get how it works, then start modifying it, potentially asking new questions here if you really need to.

<?php

$errors = false;

$email = '';
$username = '';
$password = '';

if ('POST' === $_SERVER['REQUEST_METHOD']) {
    $email = $_POST['email'];
    $username = $_POST['username'];
    $password = $_POST['password'];

    $errors = [];

    if (empty($password)) {
        $errors[] = 'You need to enter a Password';
    }

    if (empty($username)) {
        $errors[] = 'You need to enter a Username';
    }

    if (empty($email)) {
        $errors[] = 'You need to enter a Email Address';
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = "You need to have a valid Email Address";
    }
}

if ($errors) {
    echo '<pre>';
    echo implode(PHP_EOL, $errors);
    echo '</pre>';
}
?>
<form method="post">
    <label>Email <input type="text" name="email" value="<?php echo htmlspecialchars($email); ?>"/></label><br/>
    <label>Username <input type="text" name="username" value="<?php echo htmlspecialchars($username); ?>"></label><br/>
    <label>Password <input type="password" name="password"></label><br/>
    <input type="submit" value="Submit">
</form>
Chris Haas
  • 53,986
  • 12
  • 141
  • 274
  • when I do this If I put a password and nothing else it says that I need to enter a password when I did. Same problem. –  Mar 05 '21 at 18:29
  • Here's a quick demo online that shows a password is being set and nothing else. The error message is "You need to enter a Username": https://3v4l.org/QHb9C – Chris Haas Mar 05 '21 at 18:32
  • When I go there if I get rid of cheese as the password it says I need a password instead of username or email –  Mar 05 '21 at 18:36
  • and the filter validate email doesn't work –  Mar 05 '21 at 18:37
  • I have updated the example above to include multiple checks that validate the four items independently. Here is an online version for testing that also shows the email portion working. https://3v4l.org/dJf2b If you have an email address that doesn't work with that test, please post that. There are many edge cases for SMTP addresses but they are rare to see in the wild. – Chris Haas Mar 05 '21 at 18:43
  • when i added that to my code it said all three at once. and when I put in my username it was still telling me all three not all two, all three –  Mar 05 '21 at 18:58
  • Please add your updated code to your original question. – Chris Haas Mar 05 '21 at 19:05
  • @KadenSkinner, the code you posted does not match what I provided. Please make sure to include the `$isValid` parts. – Chris Haas Mar 05 '21 at 19:11
  • Ok I fixed it sorry about that –  Mar 05 '21 at 19:13
  • your link shows it does but for me it isn't working –  Mar 05 '21 at 19:14
  • If my code works and yours doesn't, it is almost definitely that the contents of `$_POST` aren't what you think they are. Please inspect those values using `var_dump` or similar. Also, please set `error_reporting(-1);` – Chris Haas Mar 05 '21 at 19:16
  • I have provided a second edit. It appears your are using GET instead of POST in your HTML – Chris Haas Mar 05 '21 at 19:20
  • I edited my code and I added `Method="post"` It didn't do anything. –  Mar 05 '21 at 19:35
  • I didn't see the AJAX portion. Remove that completely for now and set the `action` of the form to point to the `jslogin.php`. Remove all session-related code for now, too, and make sure that error reporting is set to `-1`. Once that all starts working you can add AJAX back in, but that is a different problem that should be added to a new question. – Chris Haas Mar 05 '21 at 19:38
  • can you show this code in your answer. I don't want to do this wrong. –  Mar 05 '21 at 19:43
  • @KadenSkinner, I added one last example. It probably isn't exactly what you are looking for but is instead a full-working, standalone example of how to do this. Please get that working first, then start adding additional features. – Chris Haas Mar 05 '21 at 19:58