0

I'm having trouble with my From. For some reason, when I submit a form, the email does not get saved into the database.

My html/js makes two Async - Await Ajax calls. The first grants the user internet access (Hotspot), while the 2cnd saves the email into the database. The router (Hotspot) is on a different network then the server.

Note that the 1st xhr works (the user gets internet access), the 2cnd form reports XHR2 4 and XHR2 200, but the email is not saved into the database.

I'm (currently) using XAMPP, if that is relavent. I've also added ServerName 10.30.20.30:80 in the httpd.config file.

If I can provide any additional information, let me know.

Any help solving this problem would be greatly appreciated.

Thank you

HTML

<!DOCTYPE html>
<html>
<head>
<meta content="text/html" />
<meta charset="utf-8" />

<title>HotSpot</title>

</head>
<body>

    <!-- Form za mail, ki se spravi v DB -->
    <form accept-charset="utf-8" name="mail" onsubmit="return false;" method="post" id="mail">
        <h1>Hotspot</h1>
        <h2>To gain internet access, enter your email.</h2>
        <br />
        <input type="text" id="email" name="email" autofocus="autofocus" />
        <br />
        <input type="button" value="Submit" id="submit_ok" name="submit_ok" /> <br />
    </form>

<script type="text/javascript">

document.getElementById("submit_ok").addEventListener("click", sendAjax);

async function sendAjax() {
    let ax1 = await Ajax1 ("POST", "http://10.5.50.1/login")
    let ax2 = await Ajax2 ("POST", "http://10.30.20.30/Site/anti-xss.php")
}

function Ajax1 (method, url){
    return new Promise (function (resolve,  reject){
        let xhr = new XMLHttpRequest();
        xhr.open('POST', 'http://10.5.50.1/login', true);
        xhr.onload = function(){
            if(this.status >= 200 && this.status < 300){
                resolve(xhr.response);
                console.log("Success!");
                console.log("You'r logged in.");
                console.log("XHR1 " + xhr.readyState);
                console.log("XHR1 " + xhr.status);
            }else{
                reject({
                    status: this.status,
                    statusText: xhr.statusText
                });
            }
        };
        xhr.onerror = function (){
            reject({
                status: this.status,
                statusText: xhr.statusText
            });
        };
        xhr.send("username=HSuser&password=SimpleUserPassword");
    });
}

function Ajax2 (method, url){
    return new Promise (function (resolve, reject){
        let xhr2 = new XMLHttpRequest();
        xhr2.open('POST', 'http://10.30.20.30/Site/anti-xss.php', true);
        xhr2.onload = function(){
            if(this.status >= 200 && this.status < 300){
                resolve(xhr2.response);
                console.log("Success!");
                console.log("You'r email is " + useremail + ".");
                console.log("XHR2 " + xhr2.readyState);
                console.log("XHR2 " + xhr2.status);
            }else{
                reject({
                    status: this.status,
                    statusText: xhr2.statusText
                });
            }
        };
        xhr2.onerror = function (){
            reject({
                status: this.status,
                statusText: this.statusText
            });
        };
        let useremail = document.getElementById("email").value;                 
        xhr2.send("Email="+encodeURIComponent(useremail));
    });
}

</script>   
</body>
</html>

PHP

<?php

    require ('connect.php');

    $clean_email = "";
    $cleaner_email = "";


    if(isset($_POST['Email']) && !empty($_POST['Email'])){
        //sanitize with filter
        $clean_email = filter_var($_POST['Email'], FILTER_SANITIZE_EMAIL);
        //sanitize with test_input
        $cleaner_email = test_input($clean_email);
        //validate with filter
        if (filter_var($cleaner_email,FILTER_VALIDATE_EMAIL)){
            // email is valid and ready for use
            echo "Email is valid";  
            //Email is a column in the Database
            $stmt = $DB->prepare("INSERT INTO naslovi (Email) VALUES (?)");
            $stmt->bind_param("s", $cleaner_email);
            $stmt->execute();
            $stmt->close();
        } else {
            // email is invalid and should be rejected
            echo "Invalid email, try again";
        } 
    } else {
    echo "Please enter an email";
    }

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

    $DB->close();   
?>
DrDoom
  • 297
  • 2
  • 10
  • " when I submit a form, the email does not get saved into the database."....a lot can go wrong in between those two things. You need to narrow down the problem. Do you understand how to use your browser's Developer Tools to debug an AJAX request? Have you got error logging switched on in PHP to catch any exceptions and warnings there? have you got mysqli set to throw exceptions when SQL errors occur? P.S. If I had to guess, since you're visiting a different IP address for the 2nd AJAX request, I'd be thinking maybe you're getting a CORS error somewhere. – ADyson Jan 13 '20 at 09:00
  • Hey. Thanks for the response. No, I don't have PHP nor SQL error logging turned on. Could you tell me where/how to do that. I am using F12 tools, there are no CORS errors, connect php has `header('Access-Control-Allow-Origin: *');` – DrDoom Jan 13 '20 at 09:04
  • Usually there is a bit more than that required for CORS to fully function, but if you're not seeing any errors in the Console about it then maybe it's OK. – ADyson Jan 13 '20 at 09:07
  • Enabling error reporting/logging in PHP, and enabling mysqli exception reporting, is very easy to google, but here you go anyway: https://stackify.com/php-error-logs-guide/ and https://stackoverflow.com/a/14578644/5947043 – ADyson Jan 13 '20 at 09:09
  • P.S. as an aside, also: https://stackoverflow.com/a/4559976/5947043 (for your `if` statement) – ADyson Jan 13 '20 at 09:10
  • Another thing. Your logic here is flawed: `if(this.status >= 200 && this.status < 300){ resolve(xhr2.response); console.log("Success!");...` you're assuming that all 200 error statuses indicate success, but in fact your code allows several ways for the operation to logically fail without actually changing the HTTP status (e.g. if the email parameter is empty, or if `filter_var` returns false). If such a validation error occurs, it's usually a good idea to set the HTTP status to 400, and return a suitable JSON object detailing all the validation errors. – ADyson Jan 13 '20 at 09:14
  • Thank you good sir =) PS: Thanks for the pointers. 1st I need to get the Ajax working though. – DrDoom Jan 13 '20 at 09:15
  • Thanks for the links. They were pretty straightforward. I only have a bit of trouble understanding what exactly I need to put into my php file. Do I only need to use `mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT)` or the whole code? – DrDoom Jan 13 '20 at 10:00
  • what do you mean by "whole code" exactly? That is the only line shown in the accepted answer. So in order to get mysqli to throw exceptions, you just need to add that line to your script (somewhere before you start connecting to the database. At the start of `connect.php` would probably make sense in your case). And then separately you need to configure PHP to log/report those exceptions, as per the other link I gave. – ADyson Jan 13 '20 at 10:04
  • Thanks for the clerification. There is some additional code in the answer below the accepted one. Wasn't sure if that needed to be included. Additionally, while I didn't get the CORS error before, I do get it now. Will try to resolve it. Again, thanks for the help. – DrDoom Jan 13 '20 at 10:27
  • "There is some additional code"... at https://stackoverflow.com/a/14578644/5947043? I don't see any. There's just one line of formatted code. All that follows is a description of a suggested wrapper structure to make the code simpler, but it's not a requirement. – ADyson Jan 13 '20 at 10:29
  • It works now. Thanks for the tips. I'm not sure what the problem was though. Amongst other things I added `xhr2.setRequestHeader("Content-type", "application/x-www-form-urlencoded", "Access-Control-Allow-Origin: *");` to XHR2 and I no longer get the CORS error and the emails are entered into the database now. – DrDoom Jan 13 '20 at 10:54
  • "Access-Control-Allow-Origin" is a **response** header which is intended to be set by the server (see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin). Setting it in the **request** is meaningless, it will be ignored. Think about it - if you, as the client making the request, could control what origins are allowed to make CORS requests to that server, then what would be the purpose of CORS restrictions? It would be a waste of time. – ADyson Jan 13 '20 at 10:58
  • setting the content-type header _might_ have helped, although that's normally the default content type anyway. It depends what the error was, you never told me. But more importantly: As a general rule you should change one thing at a time when debugging, so you can be sure what the effect of each change is, and can therefore be certain of the cause. Otherwise you end up unsure what parts of your code are useful or not (and down that murky road lies the horrors of [cargo-cult programming](https://en.wikipedia.org/wiki/Cargo_cult_programming)) – ADyson Jan 13 '20 at 11:00
  • Yea, my understanding of CORS is spotty at best. Did some more testing, turns out I needed the setRequestHeader, otherwise the email didn't get saved into the DB. – DrDoom Jan 13 '20 at 11:08
  • Actually... if I remove `"Access-Control-Allow-Origin: *"`, it doesn't get saved into the database. I don't get any CORS errors without it, but it doesn't save it into the DB. I'll need to do some additional testing, as perhaps the email is sent before the user actually gets internet connection and so the data is lost... PS: Where can I check the SQL logs? – DrDoom Jan 13 '20 at 11:14
  • There isn't a "SQL log" specifically. What the change I suggested does is cause the `mysqli` library to throw an exception in PHP if an error occurs while it's trying to execute the SQL query (or associated actions such as connecting to the DB, statement preparation, parameter binding etc). You then need to configure PHP to log exceptions to a file (as per the other link I gave you). Part of that configuration process involves specifying where the log file will be stored. – ADyson Jan 13 '20 at 11:39
  • Thanks. I did set up the PHP logging as instructed on the website. – DrDoom Jan 13 '20 at 11:51

1 Answers1

0

After adding getRequestHeader to XHR2 and adding half a second of delay betwen XHR1 call and XHR2 call everything seems to work.

Thank you @ADyson, you helped was invaluable =)

DrDoom
  • 297
  • 2
  • 10