HTML page with form that simply adds a line of text, permanently, to the webpage

A) I have contacted them and my hosting company says “This should not cause any problem”.

“To prevent triggering this error response, when you echo the $sql and the mysqli_error information, pass them through htmlentities() with the flag parameter set to ENT_QUOTES”

  1. Can you provide the code for this? I googled it and can’t figure out how or where to incorporate it. Everywhere I try to past it in it breaks the page.
    I assume you mean to add it to this part of the code somehow?
    } else {
    echo “Error” . $sql . “
    ” . mysqli_error($conn);

“To prevent the sql syntax error in the first place, you need to properly escape the data values being put into the sql query statement or even better and actually simpler and fool-proof-secure, use a prepared query.” as I have pointed out, I do not know how, and that is why I am here asking for help.

I tried to build the PDO statement like you keep suggesting, but there’s very few tutorials available, and my attempt (below) is breaking the page:
[php]<?php
$servername = “SERVER”;
$username = “UN”;
$password = “PW”;
$dbname = “fDB”;
$users_name = $_POST[‘name’];
$users_request = $_POST[‘requests’];
if ($_SERVER[“REQUEST_METHOD”] == “POST”) {
}
try {
$conn = new PDO(“mysql:host=$servername;dbname=$dbname”, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->beginTransaction();
$conn->exec(“INSERT INTO submissions (requests, name)
VALUES (’$users_request’, ‘$users_name’)”);
$conn->commit();
header(“Location: clv2.php”);
}
catch(PDOException $e)
{
$conn->rollback();
echo "Error: " . $e->getMessage();
}
$conn = null;
?>
[/php]
CLOSER? It’s now making that blank entry on every page load again.

oops, double posted

I’ll address some of the points in a separate reply.

Actually, I determined the urls already and you have a bunch of nonsense posts from my testing.

but php.net doesn't give one any reference on where in the code one would place their suggested...

That’s because programming is not like painting by the numbers, i.e. put “code A” (green paint) on all the number 1’s, put “code B” (blue paint) on all the number 2’s. Context is very important in programming. So, take the statement - “When you output data on a web page is when you would apply htmlentities() to the data …”. Where in your code are you (dynamically) outputting data on the page? In submissions.php, the data from the SELECT query and the message about no submissions to display, in formcode.php, when there is query error and you display $sql and the msyqli_error information, and for any form action=’…’ attribute where you are using $_SERVER[‘PHP_SELF’], which BTW, you can just leave the action attribute completely out and a html5 form will be submitted to the same page it is on.

I *thought* that this part in my code was doing that process?

The test_input() function is being called on the data that is the input to your code. This is not at the point where you are outputting something to the web page.

How would it get requested by a GET request ...

By posting url’s to it in forums that get indexed by search engines. Search engines will ONLY make get requests. If you ALWAYS enclose your post method form processing code in a test so that it will only be executed when there is a post request, your page won’t waste resources and won’t output php errors in response to search engines indexing your site.

I'm not requiring any fields, all fields are optional. People are welcome to submit a request without giving a name.

Then, the ‘requests’ field is required and you don’t want to waste time and resources inserting data if the ‘requests’ is empty.

All I *want* to do is trim out the apostrophes and replace them with the correct character entity.

No, that’s not what you want. I believe my reply above this on addresses why you are getting the error response, but your web host should be able to give you definitive information. There are several hundred million web sites that happily accept data containing single-quotes. When you have a problem in a technical subject like programming, you must find the actual cause of the problem before you can fix it, otherwise all you are doing is trying to make symptoms disappear by putting a band-aid over the top of them. This just wastes a bunch of time.

Arrays are variables with more than one dimension. Arrays are for sets of data, that will be treated the same. If you had any algebra in school, you should have seen arrays for sets of numbers. Arrays will let you loop over data, rather than writing out code for each possible variable. Programming is already a tedious and error prone typing-activity. By cutting down on the repetitive coding, you will save time when writing, testing, and debugging problems. It wold be to your advantage to do some research and experimenting on using arrays.

The examples in the php.net documentation do show WHAT code does. It’s up to the programmer to take what the code does and use it where will accomplish something useful. For example, converting from msyqli to PDO. What basic tasks are you using mysqli for in your code -

  1. Making a database connection.

  2. Forming and running sql queries - SELECT and INSERT (and later UPDATE and DELETE and a few others.)

  3. For SELECT queries, testing the number of rows the query matched and fetching the data from the query.

All you would need to do is learn what the equivalent PDO statements are for these tasks.

Using prepared queries involves using place-holders in the sql query statements, instead of putting variables in directly. This actually simplifies the sql syntax, since any single-quotes you have around string values will be eliminated. Instead of executing the query you have formed, you prepare it, then there is an additional execution() step, where you supply the actual data values and cause the query to be executed with that data (you can repeat the data/execution step multiple times, without needing to prepare the query again.) It is here the the PDO extension becomes much simpler than the mysqli extension. The mysqli extension requires an explicit bind step before execution and fetching data from a mysqli prepared query requires binding result variables in adding to calling a fetch statement.

Ok, I now have a page that is working correctly for fixing the apostrophe issues, however, I had to remove just about everything and start over, and now it’s adding a blank entry at every page load. The if ($_SERVER[“REQUEST_METHOD”] == “POST”) line doesn’t seem to be stopping it from posting regardless of if there has been a submission or not. Since this is a whole new way of doing this page, is there a different way to deal with if ($_SERVER[“REQUEST_METHOD”] == “POST”) now? And is this secure?

LINK: http://phaewryn.net/fa/clv3.php

[php]

<?php $servername = "my_server"; $username = "my_username"; $password = "my_password"; $dbname = "my_database"; $users_name = htmlentities($_POST['name'], ENT_QUOTES, 'UTF-8'); $users_request = $_POST['requests']; if ($_SERVER["REQUEST_METHOD"] == "POST") { } try { $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $conn->beginTransaction(); $conn->exec("INSERT INTO submissions (requests, name) VALUES ('$users_request', '$users_name')"); $conn->commit(); header("Location: clv3.php"); } catch(PDOException $e) { $conn->rollback(); echo "Error: " . $e->getMessage(); } $conn = null; ?>

[/php]

<form method="POST" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
Make A Request:<br>
<textarea name='requests' id='requests'></textarea> <br>
Your Name (a-z only):<br>
<input type='text' name='name' id='name'/><br>
<input type='submit' value='Send' class='button'>  
</form>

Phaewryn

Sorry, i thought you wanted to secure your webpage from hacking etc. hence PDO.

The if ($_SERVER["REQUEST_METHOD"] == "POST") line doesn't seem to be stopping it from posting regardless of if there has been a submission or not

That’s because your form processing code isn’t inside the conditional block { … }.

I recommend that you look at your code and identify where the start and end of the form processing code is, and then look where the opening { and closing } of the if(){…} statement are at.

When I tried to move the closing tag to make the “if ($_SERVER[“REQUEST_METHOD”] == “POST”)” surround all the content, the entire page stopped working, so I moved it back temporarily so you could see the page’s function at present. I don’t know where to put the tag. If I enclose everything, the page doesn’t load at all. I’ll figure it out, just got sleepy last night and gave up.

I do, so I have switched to that method, and I think I’ve got it now! Is this secure?
[php]

Candlelight Vigil <?php $servername = "my_server"; $username = "my_username"; $password = "password"; $dbname = "db"; $users_name = htmlentities($_POST['name'], ENT_QUOTES, 'UTF-8'); $users_request = htmlentities($_POST['requests'], ENT_QUOTES, 'UTF-8'); if ($_SERVER["REQUEST_METHOD"] == "POST") { try { $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $conn->beginTransaction(); $conn->exec("INSERT INTO submissions (requests, name) VALUES ('$users_request', '$users_name')"); $conn->commit(); header("Location: clv.php"); } catch(PDOException $e) { $conn->rollback(); echo "Error: " . $e->getMessage(); } $conn = null; } ?>
"> Make A Request:

Your Name (a-z only):

candle

As we light our candles, we honor those who need strength, and send the healing gift of love with all our hearts, may it flow into the brokenhearted who are tending the sick, and bring them comfort in their time of need. We send them our love, may it bolster their strength and comfort their hearts to be held in the loving embrace of this family of fellow feline caretakers.

As we light our candles, we send strength and comfort to those kitties who struggle with their illness this week, may our love bring them relief and peace, aiding in their quick recovery.

As we hold our candle close to our heart, we read the names of the sick and those with special needs, granting them their request, manifesting that it be done, in love, in trust, and in time that it may assist them to conquer through their time of need.

			<div id="myrequest">
			<?php include("submissions.php"); ?>
			</div>

As we light our candles, we also send our heartfelt love and thankfulness to those kitties who have departed this week. May they know the gratitude we hold in our hearts for the gift of unconditional love they blessed us with, although their time was short, they are forever remembered.

			<div id="memorial"><p>(insert departed kitties here)</p></div>
		</div>
	</div>
</div>
[/php]

Submissions.php (the include - I assume I need to switch this file to PDO as well?):
[php]

<?php $servername = "my_server"; $username = "my_username"; $password = "password"; $dbname = "db"; // Create connection $conn = mysqli_connect($servername, $username, $password, $dbname); // Check connection if (!$conn) { die("Connection failed: " . mysqli_connect_error()); } $sql = "SELECT id, requests, name FROM submissions"; $result = mysqli_query($conn, $sql); if (mysqli_num_rows($result) > 0) { // output data of each row while($row = mysqli_fetch_assoc($result)) { echo "" . $row["requests"]. " - by " . $row["name"]. "
"; } } else { echo "no special requests this week"; } mysqli_close($conn); ?>

[/php]

Is this secure?

No. You are not using a prepared query, you are still doing some things that someone has written not to do, and you have additional things present that are not correct or can stop working when moving between different server configurations.

Just using the php PDO extension doesn’t make your code safe against anything. Using a prepared query will make your code safe against sql special characters from breaking the sql query syntax, which is how sql injection is accomplished. The PDO extension makes using prepared queries easier. This however will only make the part of the code that’s executing database queries safe.

You must also apply htmlentities() to data that’s being output on the web page. You are still applying it to the data being input to your sql query statement (I recommend that you re-read my replies in this thread.)

Here’s a list of problems and things to improve in the current code -

  1. The post method form processing code needs to be near the top of your file, before the start of the html document.

  2. You should put your database connection credentials and the connection code in a .php file and ‘require’ it into any code that needs a connection.

  3. You should use ‘require’, not ‘include’ when bringing in an external .php script file that you page ‘requires’ for it to work.

  4. require/include are not functions and don’t need the () around the value. The () are just adding clutter to your code.

  5. You should only make ONE database connection on any page, at a common point where all the code on a page that needs a connection can use it.

  6. As has been stated multiple times, htmlentities() is an output function. You use it on data being output on the web page. Why are you still using it on the input $_POST data that you are supplying to the sql query statement?

  7. The two lines of code (incorrectly) applying htmlentities() to the two $_POST variables are part of your form processing code. Why aren’t they inside the if(){…} with all the other form processing code?

  8. Don’t copy variables to other variables for no purpose. This is just make-work wasted typing time. After you remove the htmlentities() usage from the two $_POST varaibles in your form processing code, you would be left with $some_var = $_POST[‘some_index’];. If you find yourself with code that looks like this, stop and consider that the original variable is perfectly fine to use in the rest of the code and copying it to another variable is a waste of time and is just cluttering up your code.

8.1) You need to trim() submitted data before validating it, so that you can detect data that consist of all white-space characters.

  1. When you make the PDO connection, you need to set the character set for the connection, turn off emulated prepared queries, and if you set the default fetch mode to assoc, you won’t have to specify it in every fetch statement.

  2. You should not put a try/catch block in your code unless needed and you should not echo the database error messages onto the web page. The only time you should put a try/catch block in your code is if your code must handle a specific error, such as a duplicate key error. For connection and most PDO statement errors, you should just let php catch the exception and handle the error for you. Php will use its error_reporting, display_errors, and log_errors settings to control what happens with the actual error information. This will allow you to display the error information when learning, developing, and debugging code, and log the error information when running your code on a live/public server, simply by changing the php display_errors/log_errors settings. This will also simply your code, since you can remove the try/catch block you have now.

  3. Database transactions have a purpose, but what you doing at this point isn’t one of them. Don’t use beginTransaction(), commit(), and rollback() unless you are doing something that actually is using a transaction.

  4. As posted above in this thread, a prepared query has place-holders in the sql query statement for the values. You would also call the prepare() method, not the exec() method, and you would supply the two data values when you execute the query.

  5. Any header() redirect needs an exit; statement after it to prevent the rest of the code on the page from running. A header() doesn’t stop code execution.

  6. You should generally let php automatically close a database connection for you when the php script ends.

  7. If there is a data validation error, you need to re-populate the form fields with any submitted data, so that the visitor doesn’t need to re-type in anything. Just correct whatever the validation error is. You have indicated that the ‘requests’ field is required. Do you want to make the visitor re-type in their name if they have accidentally hit the submit button before typing in a ‘requests’?

  8. The submissions.php code should not be in a separate file. this is just creating more pieces of code that you must maintain. Before the start of your html document, after the end of the post method form processing code, you should execute the SELECT query and retrieve the data into a php variable. In the html document where you want to display the data, just test/loop over the php variable. This will separate the concerns in your code, making it easier to design, write, test, debug, and maintain your code.

  9. There are people that have names that contain more than just A-Z characters. Any prompt you display and any validation you do on the submitted data, needs to use the same rules.

Ok, let’s start here. You said that I’ve now made using prepared queries easier for myself (great). Teach me how to prepare my query and where I would insert my prepared query into my code.

Google wasn’t helpful when searching “prepared query php” and this page is the closest thing I could find to the topic:
http://php.net/manual/en/pdo.prepared-statements.php and it is about prepared STATEMENTS, not queries. How does a prepared query differ from a prepared statement?

I need to add these lines back in now that I’ve switched to PDO, but where do I put them in the code? After the $conn->beginTransaction(); line?
[php]
$stmt = $conn->prepare(“INSERT INTO submissions (requests, name) VALUES (?, ?)”);
$stmt->bind_param(“ss”, $users_request, $users_name);
[/php]

Submissions.php page now also in PDO format (progress):
[php]<?php
$servername = “my_server”;
$username = “my_username”;
$password = “my_passowrd”;
$dbname = “my_db”;
$charset = ‘utf8’;
$users_name = htmlentities($_POST[‘name’], ENT_QUOTES, ‘UTF-8’);
$users_request = htmlentities($_POST[‘requests’], ENT_QUOTES, ‘UTF-8’);
$dsn = “mysql:host=$servername;dbname=$dbname;charset=$charset”;
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO($dsn, $username, $password, $opt);
$stmt = $pdo->query(‘SELECT id, requests, name FROM submissions’);
while ($row = $stmt->fetch())
{
echo $row[‘requests’] . "   ⋅ " . $row[‘name’] . “
”;
}
?>
[/php]

Any obvious errors/omissions on this page’s code that need addressing? (I’m working my way down the list)

The php goes at the very top of the file? Above the tag? Not in the tag? Ok, done!

DONE! (erm, I think, I just moved all the php from the clv.php page to a creds.php file and required it in like the submissions are done, and it worked, so I guess that’s what you mean)

NOTED! Thank you, I will make that change. <?php require"submissions.php"; ?> is correct now?

Because it made the page work so that I could enter apostrophes in the form fields. If I remove it from this page, leaving only $users_name = $_POST[‘name’]; $users_request = $_POST[‘requests’]; then the page errors to “The requested URL was rejected. If you think this is an error, please contact the webmaster. Your support ID is: 13509873613080608169”. If you have a solution, I’m all ears!

Is having two php requires and a form submission on a webpage considered making three different database connections? I have no idea how I’d make the page any other way. Here’s the webpage code now:

<?php require"creds.php"; ?>
<!DOCTYPE html>
<html lang="en-US">
	<head>
		<meta charset="utf-8">
		<link rel="stylesheet" type="text/css" href="clv.css">
		<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css"> 
		<meta name="robots" content="noindex,nofollow">
		<title>Candlelight Vigil</title>
	</head>
	<body>
		<script>
		function ignite() {
			document.getElementById("candle").src="candle.gif";
			}
		</script>
<div class="container">
	<div class="w3-row">
		<div class="w3-third w3-container w3-padding-0 w3-margin-0 w3-display-container" style="height:100vh;">

			<div class="w3-display-topleft">
				<div class="submissions">
					<form method="POST" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
					Make A Request:<br>
					<textarea name='requests' id='requests'></textarea> <br>
					Your Name (a-z only):<br>
					<input type='text' name='name' id='name'/><br>
					<input type='submit' value='Send' class='button' name='submit'>  
					</form>
				</div>
			</div>
		<div class="w3-display-topright"></div>
		<div class="w3-display-bottomleft"></div>
		<div class="w3-display-bottomright"></div>
		<div class="w3-display-left"></div>
		<div class="w3-display-right"></div>
		<div class="w3-display-middle"></div>
		<div class="w3-display-topmiddle"></div>
		<div class="w3-display-bottommiddle">
			<div id="light">
				<img id="candle" src="unlitcandle.gif" alt="candle" onclick="ignite()">
			</div>
		</div>
		</div>
		<div id="dedication" class="w3-container w3-twothird">
			<div class="dedication-container">
<p>As we light our candles, we honor those who need strength, and send the healing gift of love with all our hearts, may it flow into the brokenhearted who are tending the sick, and bring them comfort in their time of need. We send them our love, may it bolster their strength and comfort their hearts to be held in the loving embrace of this family of fellow feline caretakers.</p>
<p>As we light our candles, we send strength and comfort to those kitties who struggle with their illness this week, may our love bring them relief and peace, aiding in their quick recovery.</p>
<p>As we hold our candle close to our heart, we read the names of the sick and those with special needs, granting them their request, manifesting that it be done, in love, in trust, and in time that it may assist them to conquer through their time of need.</p>
				<div id="myrequest">
				<?php require"submissions.php"; ?>
				</div>
<br>
<p>As we light our candles, we also send our heartfelt love and thankfulness to those kitties who have departed this week. May they know the gratitude we hold in our hearts for the gift of unconditional love they blessed us with, although their time was short, they are forever remembered.</p>
				<div id="memorial"><p>(insert departed kitties here)</p></div>
			</div>
		</div>
	</div>
</div>
</body>
</html>

Point made, I have moved them as shown below. (note that I cannot remove the “incorrectly applied htmlentities()” because if I do so, the entire page breaks to an irresolvable error state upon any apostrophes being entered into a form field and since my name contains an apostrophe I do not find this acceptable. I am OK with this one problem existing, it’s not hurting anything as far as I can tell.

[php]<?php
$servername = “server”;
$username = “un”;
$password = “pw”;
$dbname = “db”;
try {
$conn = new PDO(“mysql:host=$servername;dbname=$dbname”, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->beginTransaction();
if ($_SERVER[“REQUEST_METHOD”] == “POST”) {
$users_name = htmlentities($_POST[‘name’], ENT_QUOTES, ‘UTF-8’);
$users_request = htmlentities($_POST[‘requests’], ENT_QUOTES, ‘UTF-8’);
$conn->exec(“INSERT INTO submissions (requests, name)
VALUES (’$users_request’, ‘$users_name’)”);
$conn->commit();
header(“Location: clv3.php”); }
}
catch(PDOException $e)
{
$conn->rollback();
echo "Error: " . $e->getMessage();
}
$conn = null;
?>
[/php]

Am I getting closer now?

[php]<?php
$servername = “server”;
$username = “un”;
$password = “pw”;
$dbname = “db”;
$charset = ‘utf8’;
$dsn = “mysql:host=$servername;dbname=$dbname;charset=$charset”;
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$conn = new PDO($dsn, $username, $password, $opt);
if ($_SERVER[“REQUEST_METHOD”] == “POST”) {
$users_name = trim($_POST[‘name’]);
$users_name= filter_var($_POST[‘name’], FILTER_SANITIZE_STRING);
$users_request= filter_var($_POST[‘requests’], FILTER_SANITIZE_SPECIAL_CHARS);
$stmt = $conn->prepare(“INSERT INTO submissions(requests, name) VALUES(:users_request, :users_name)”);
$stmt->execute(array(’:users_request’ => $users_request, ‘:users_name’ => $users_name));
$affected_rows = $stmt->rowCount();
}
?>
[/php]

[php]<?php
$servername = “server”;
$username = “un”;
$password = “pw”;
$dbname = “db”;
$charset = ‘utf8’;
$dsn = “mysql:host=$servername;dbname=$dbname;charset=$charset”;
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO($dsn, $username, $password, $opt);
$stmt = $pdo->query(‘SELECT id, requests, name FROM submissions’);
while ($row = $stmt->fetch())
{
echo $row[‘requests’] . "   ⋅ " . $row[‘name’] . “
”;
}
?>
[/php]

I will tackle more of your endless list of my mistakes tomorrow! Hope I am at least not frustrating you half to death. I really do sincerely appreciate all your help, and I swear, I am learning! :smiley:

Sponsor our Newsletter | Privacy Policy | Terms of Service