0

I'm trying to use an HTML dropdown form in order to let the user choose which table from the database to display. This part works fine, but I want them to be able to add to whichever table they choose. I've created the form for it but once they hit submit on that form it unloads the table they selected and fails to add the data to the table.

This is the code for the main page; body.php:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Contact Form - PHP/MySQL Demo Code</title>
</head>
<style>
table, th, td {
  border:1px solid black;
}
</style>
<body>

<form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']) ?>" method="post">
    <div>
        <label for="dbselect">Select Table:</label><br>
        <select name="dbselect" id="dbselect">
            <option value=""><-- Choose Table --></option>
            <option value="messages">messages</option>
            <option value="messages2">messages2</option>
        </select>
    </div>
    <div>
        <button type="submit">Select</button>
    </div>   
</form>

<?php
    session_start();
    
    include 'get.php'; 
    $_SESSION["dbselect"] = filter_input(INPUT_POST, 'dbselect', FILTER_SANITIZE_STRING);                               
    if ($_SESSION["dbselect"] == "messages") {
        dbMessages("*");
        include 'Forms/contact_form.php';
    }
    if ($_SESSION["dbselect"] == "messages2") {
        dbMessages2("*");
    }                    
    
?>
</body>

This is the code that actually prints the tables, which I believe works fine; get.php:

<?php
function display_data($data) {
    $output = "<table>";
    foreach($data as $key => $var) {
        //$output .= '<tr>';
        if($key===0) {
            $output .= '<tr>';
            foreach($var as $col => $val) {
                $output .= "<td>" . $col . '</td>';
            }
            $output .= '</tr>';
            foreach($var as $col => $val) {
                $output .= '<td>' . $val . '</td>';
            }
            $output .= '</tr>';
        }
        else {
            $output .= '<tr>';
            foreach($var as $col => $val) {
                $output .= '<td>' . $val . '</td>';
            }
            $output .= '</tr>';
        }
    }
    $output .= '</table>';
    echo $output;
}

function dbMessages($selector) {
    include 'db.php';
    $query = "SELECT $selector FROM messages";
    $res = mysqli_query($conn,$query);
    display_data($res);
}

function dbMessages2($selector) {
    include 'db.php';
    $query = "SELECT $selector FROM messages2";
    $res = mysqli_query($conn,$query);
    display_data($res);
}      
        

And this is the code that is supposed to display the form and upload the data into the table; contact_form.php:

<?php

include 'db.php';
if ((isset($_POST["Submit"])) && (!empty($_POST["txtName"])) && (!empty($_POST["txtPhone"])) && (!empty($_POST["txtEmail"])) && (!empty($_POST["txtMessage"]))) {
    $txtName = $_POST['txtName'];
    $txtEmail = $_POST['txtEmail'];
    $txtPhone = $_POST['txtPhone'];
    $txtMessage = $_POST['txtMessage'];
    $query = "insert into messages(ID, name, email, phone, message) values (NULL, 
                '$txtName', '$txtEmail', '$txtPhone', '$txtMessage')";
    
    $res = mysqli_query($conn , $query);
    
    mysqli_close($conn);
    unset($_POST);
    echo "<meta http-equiv='refresh' content='0'>";
}

echo '
<fieldset>
<legend>Contact Form</legend>
<form name="frmContact" method="post" action="index.php?send=1" target="_self">
<p>
<label for="Name">Name </label>
<input type="text" name="txtName" id="txtName" >
</p>
<p>
<label for="email">Email</label>
<input type="text" name="txtEmail" id="txtEmail">
</p>
<p>
<label for="phone">Phone</label>
<input type="text" name="txtPhone" id="txtPhone">
</p>
<p>
<label for="message">Message</label>
<textarea name="txtMessage" id="txtMessage"></textarea>
</p>
<p>&nbsp;</p>
<p>
<input type="submit" name="Submit" id="Submit" value="Submit">
</p>
</form>
</fieldset>
'
?>

This is the observed process:

I select which table to display using dropdown menu and hit select.

Selected table successfully appears with its form.

I enter data into form and hit submit.

The dropdown menu returns to it's default state and the table unloads.

Entered data fails to be added to table.

This is the expected process:

I select which table to display using dropdown menu and hit select.

Selected table successfully appears with its form.

I enter data into form and hit submit.

Selected table stays on the page and submitted data is successfully added.

It should be noted that the contact_form.php file is only for the first table, messages, and not for messages2.

ADyson
  • 57,178
  • 14
  • 51
  • 63
Gabriel
  • 19
  • 1
  • Fails how? Have you got all error reporting enabled? See [How to get the actual mysqli error](https://stackoverflow.com/a/22662582/5947043) for instructions on enabling PHP and mysqli error reporting (or logging to a file, in a live environment) – ADyson Jun 23 '22 at 15:13
  • 1
    **Warning:** Your code is vulnerable to SQL Injection attacks and syntax errors. You should use parameterised queries and prepared statements to help prevent attackers from compromising your database by using malicious input values. http://bobby-tables.com gives an explanation of the risks, as well as some examples of how to write your queries safely using PHP / mysqli. **Never** insert unsanitised data directly into your SQL. The way your code is written now, someone could easily steal, incorrectly change, or even delete your data. – ADyson Jun 23 '22 at 15:14
  • https://phpdelusions.net/mysqli also contains good examples of writing safe SQL using mysqli. See also the [mysqli documentation](https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php) and this: [How can I prevent SQL injection in PHP?](https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php) . Parameterising your queries will also greatly reduce the risk of accidental syntax errors as a result of un-escaped or incorrectly quoted input values. If you learnt your current technique from a tutorial or book, please don't use it again. – ADyson Jun 23 '22 at 15:14
  • @ADyson I don't think it's explicitly a problem with the mysql code. If I were to remove the ability to select which table to use and just had the contents of contact_form.php inside of body.php then it'd upload and display everything fine. I think the problem is more with the php and html present in my code. – Gabriel Jun 23 '22 at 15:18
  • Well your mysql code is still faulty and vulnerable, for the reasons I've listed. Even leaving aside the security issue, a simple `'` in one of the input fields would crash the SQL due to the quote marks being out of sync. Parameterisation entirely removes that risk. – ADyson Jun 23 '22 at 15:23
  • Anyway regarding the rest of your logic, the contact form posts back to `index.php`, but the logic to insert the contact form data appears to be in `contact_form.php`. You haven't shown us anything about index.php so not sure what that does. – ADyson Jun 23 '22 at 15:24
  • @ADyson the index.php form just has include commands for header.php, body.php, and footer.php. I've only worked on body.php right now so that's the only one of the 3 that are relevant. – Gabriel Jun 23 '22 at 15:39
  • 1
    Constant [FILTER_SANITIZE_STRING](https://stackoverflow.com/questions/69207368/constant-filter-sanitize-string-is-deprecated) is deprecated. Please stop using it. – Dharman Jun 23 '22 at 15:49

1 Answers1

2

This line in your body.php:

$_SESSION["dbselect"] = filter_input(INPUT_POST, 'dbselect', FILTER_SANITIZE_STRING);

runs every time that page is called, regardless of whether the form containing the dropdown has been submitted or not.

This therefore overwrites the Session value before your code has chance to check what it is. This means that when the contact form is submitted, it still tries to get the dbselect value from $_POST, will fail, and therefore set the Session value incorrectly, removing what was set when the table selection form was last submitted.

You just need to check whether that form has been submitted before overwriting the Session value.

Also FILTER_SANITIZE_STRING is deprecated, you should stop using it, and you don't need that sort of filter in this context anyway.

if (isset($_POST["dbselect"])) {
  $_SESSION["dbselect"] = $_POST["dbselect"];
}
ADyson
  • 57,178
  • 14
  • 51
  • 63