I want to let user input two variable, Name and Password in a form. I want to disable any XSS or script insert in the input values. I have the following code in the form method:
<form name="form1" method="post" action="checkpw.php">
Your Name:
<table>
<tr><td><input class="text" name="name" onBlur="capitalize(this);" maxlength=12 type="text" /></td></tr>
</table>
Password:
<table>
<tr><td><input class="text" name="passwd" maxlength=8 type="password" /></td></tr>
<tr><td align="center"><br/>
<input class="text" type="submit" name="submitbt" value="Login" />
</td></tr>
</table>
and the following checkpw.php:
<?php
// Clean up the input values
$post = filter_input_array(INPUT_POST, array(
'name' => FILTER_SANITIZE_STRING,
'pw' => FILTER_SANITIZE_STRING,
));
if (is_null($post) || in_array(null, $post)) {
header("location:login.php");
return; // missing fields (or failed filter)
}
// pw is the password sent from the form
$pw=$_POST['passwd'];
$name=$_POST['name'];
if($pw == 'testpass'){
header("location:index.php");
} else {
header("location:wrong.php");
}
?>
Is this a secure way to ensure the form is sent to the server and executed ONLY after the input values have been sanitized?
Also, the $name value i want to pass it to index.php file. I insert a code in the index.php as follow:
<?php echo $name ?>
But it's empty. Any idea how to resolve it?
You are issuing a header( .. ), that means that you are redirecting to another page and start all over.
You have 3 options:
put your $name in the session.
pass the $name in the header function, like header("location: index.php?name=$name");
do not redirect, but include the php file. In that case you do not need a session at all. Will be faster also, because you do not need a round trip to the browser.
As for sanitizing, for a start it will do. It depents what you later on will do with the data. I would suggest, if putting the data in a database to look in more detail what to do.
The magic_quotes_gpc should be disabled on most servers by now; however, do read this article to see other ways of disabling them.
Furthermore, you can use filter_input_array() (PHP >= 5.2) for this purpose:
$post = filter_input_array(INPUT_POST, array(
'name' => FILTER_SANITIZE_STRING,
'pw' => FILTER_SANITIZE_STRING,
));
if (is_null($post) || in_array(null, $post)) {
return; // missing fields (or failed filter)
}
// you can safely use $post['name'] and $post['pw'] here
Related
I am trying to create php multipage forms, and I use PHP sessions for this purpose.
However, when there is an error in user input and I want the form to ask user to fill in the form again with correct inputs, the forms field will not hold the data that the user has already put in so the user has to start things all over again.
How to make forms sticky with php session?
Thanks
My code is as bellow
<?php
// Session starts here.
if (!isset($_SESSION)) session_start();
?>
<form action="registration.php" method="post">
<center><h8>Please create your user name and password</h8></center>
<div class="imgcontainer">
<img src="phone.gif" alt="Welcome" class="avatar">
</div>
<div class="container">
<label><b>Username</b></label>
<input type="text" placeholder="Enter Username" name="username" required value="<?php if(isset($_POST['username'])) echo $_POST['username'];?>">
<label><b>Password</b></label>
<input type="Password" placeholder="Enter Password" name="password" required>
<label><b>Confirm Password</b></label>
<input type="Password" placeholder="Confirm Password" name="confirm" required>
<span id="error" width=100%>
<!---- Initializing Session for errors --->
<?php
if (!empty($_SESSION['error'])) {
echo "<error>".$_SESSION['error']."</error>";
unset($_SESSION['error']);
}
if (isset($_POST['username'])){
$_SESSION['username'] = $_POST['username'];
echo $_SESSION['username'];
echo $_POST['username'];
}
?>
</span>
<br>
<input type="reset" value="Reset" />
<input type="submit" value="Next" />
</div>
and the registration php contains
<?php
if (!isset($_SESSION)) session_start();
// Checking first page values for empty,If it finds any blank field then redirected to first page.
if (isset($_POST['username']))
{
if (($_POST['password']) === ($_POST['confirm']))
{
foreach ($_POST as $key => $value)
{
$_SESSION['post'][$key] = $value;
}
}
else
{
$_SESSION['error'] = "Password does not match with Confirm Password.";
if (isset($_POST['username'])){
$_SESSION['username'] = $_POST['username'];
echo $_SESSION['username'];
echo $_POST['username'];
}
header("location: createlogin.php"); //redirecting to first page
}
}
Something like this:
<input name="var" value="<?= isset($_SESSION['var']) ? $_SESSION['var'] : null ?>" />
Try the other way around. Linking the form-action to the current page, and if all fields are valid; redirect it to the next page (registration.php). This way you'd still have all the post-data, you can process everything that needs to be saved in the session- and you can redirect after all of the logic is done.
My two cent would be keep the same page to validate the content and for the form.
You can include other PHP files from a single page depending on if the form is valid.
This way, you keep the same $_POST between both pages and don't need to store the posted data in a session variable.
Otherwise, if you want to keep the same architecture, you need to use the $_SESSION variables instead of the $_POST ones in your input value, such as the answer by delboy.
Replace:
<?php if(isset($_POST['username'])) echo $_POST['username'];?>
With:
<?php if(isset($_SESSION['username'])) echo htmlspecialchars($_SESSION['username']); ?>
^ Note: htmlspecialchars is used to prevent a reflected XSS if the users enters " as username.
The problem is, your data posted to registration.php, so you can't get the posted value in your original file. You are trying to use $SESSION but that's not recommended, and not right. Your whole solution is wrong.
Forget about session and separated files, put everything to registration.php file together.
You can check if user posted or not with $_SERVER['REQUEST_METHOD'] variable.
if($_SERVER['REQUEST_METHOD'] == 'POST'){
print 'Something just posted';
}
PS: Don't forget secure the password before you store it! :)
I'm writing a plugin which calls an API and uses an email address as part of the authentication.
I'm getting really confused regarding which way round parts of my code should go in terms of variables, and as such keep getting undefined variable errors.
This function outputs a form on a Worpdress admin page and allows the user to input their email address. I wish to sanitise the email after it has been input, then spit back out the sanitised version into the input field.
function dotmailer_options() {
?>
<div class="wrap">
<h2>Dotmailer API information</h2>
<form method="post" action="options.php">
<?php settings_fields( 'settings-group' ); ?>
<?php do_settings_sections( 'settings-group' ); ?>
<label>API key</label><br />
<input type="email" name="apiemail" value="<?php echo $sanitized_email; ?>"><br />
<label>Password</label><br />
<input type="password" name="apipassword" value="<?php echo get_option('apipassword'); ?>"><br />
<p><input type="submit" value="Save" class="button-primary" /></p>
<?php
// Store email field as var
$apiemail = get_option('apiemail');
// Sanitize var
$sanitized_email = filter_var($apiemail, FILTER_SANITIZE_EMAIL);
?>
</form>
</div>
However when I do this I get an "undefined" error actually in the input box.
I understand this is probably because the code to create $sanitized_email runs after the input has called for it, but I can't work out how else I should do this.
Also will having code directly in this function open me up to attacks? I have the following at the top of my plugin code: defined('ABSPATH') or die(); - but I don't know if that is enough.
you will need to use either javascript or ajax for this as php is server code rather than browser code (i.e. it runs on the serverside only) whilst javascript is browser code and can re-act to changes in the browser.
But there is no point in sanitizing at this stage, but you would of course sanitize and validate the form submission $_POST items. If displaying variable information from $_POST or the database to the user, you escape the values before inputting them into html.
You could validate the email using javascript to speed things up for the user if there is an issue..
<script>
function validateEmail() {
var x = document.forms["myForm"]["apiemail"].value;
var atpos = x.indexOf("#");
var dotpos = x.lastIndexOf(".");
if (atpos< 1 || dotpos<atpos+2 || dotpos+2>=x.length) {
document.elements["apiemail"].value = "Invalid email";
return false;
}
}
</script>
and in your form:
<input type="email" name="apiemail" value="" onchange="validateEmail()">
I think the reason you're getting an undefined error is you haven't defined the variable in advance - Try putting…
$sanitized_email = "";
in before your form processing code.
Also, are you using some form of checking if the form has been set or not? You can use a hidden field and check if_isset using php to see if the user has attempted to process the form. Only then would the sanitized variable be needed.
How can I refresh a page with a form on submission pending the outcome of the submitted data and display a result.
e.g I have a page with a form:
<form action="" method="post">
<input type="name" value="" name="name" placeholder="Your Name" />
<input type="button" name="submit" value="submit form "/>
</form>
The engine that handles the form is external, but required in the page:
require_once 'form_engine.php';
form_engine.php checks the input,
$success = "true";
$errorMessage = " ";
$name = $_POST['name'];
if ( $name == '') {
$errorMessage = 'Please enter your name';
$success = false;
}
else (if $success = true) {
// do something with the data
}
The form page contains the result:
<form action="" method="post">
<input type="name" value="" name="name" placeholder="Your Name" />
<input type="button" name="submit" value="submit form "/>
</form>
<p><?php echo $errorMessage; ?></p>
Will the error message get displayed after the form is submitted incorrectly? Or do I have to use a session to store it?
You need something like this:
if (!isset($_POST['name']))
instead of
if ( $name == 'name')
UPDATE
Try this, it should give you the idea:
<?php
$errorMessage = false;
if (isset($_POST['submit'])) {
if (!isset($_POST['name']) || $_POST['name']=='') {
$errorMessage = 'Please enter your name';
}
else {
// do something with the data
echo "Success!!";
}
}
?>
<form method="post">
<input type="name" value="" name="name" placeholder="Your Name" />
<input type="submit" name="submit" />
</form>
<p><?php if ($errorMessage) echo $errorMessage; ?></p>
Note: leaving out the action attribute will just submit the form to the current page
Note 2: The PHP here could very well be stored in another page. Using require() is the same as putting the code directly into the page.
You can use redirect on php side:
header('Location: www.mysite.com/index.php');
You seem to be a little confused in terms of the exact process that occurs in terms of rendering a page, as do some of those commenting. You do not need to use sessions to solve this problem. There is no need to store anything server-side between page requests because the user's browser with retain everything that you need, at least for this situation. My guess is the others took you mentioning an "external engine" and thought that the form would be submitting away to a different site/page.
form loops
Below is a diagram showing a typical form request loop:
You do not have to do this, as coding is as much about personal preference to anything else, but typically people will design their form to submit back to the same URI that generated it — as you seem to be doing in your example, by leaving the action attribute blank. By doing this, as long as you embed everything you wish to pass back to the server side within the form — each time the user submits — that information will be resent and be available in PHP.
Obviously you need to be wary of what information might constitute as sensitive, as this data should only ever be written into markup if your requests are protected by HTTPS/SSL. You should also filter/escape any user input to prevent markup injection into your site. You can prevent many problems by using htmlentities, however this can cause issues depending on the values you are trying to capture from the user. Because you are using double quoted HTML attributes (the right way to do them ;) I have not set the ENT_QUOTES option.
back to the point
So in the above loop the user will be shown the form for the first time, and after any subsequent submit, which means that each time your PHP notices that there is an error you can just add your message into the page flow. The trick with this kind of system is what exactly do you do once the form is fully complete. To get out of the loop most people will use a header location call:
<?php
require_once 'form_engine.php';
$name = !empty($_POST['name']) ? trim($_POST['name']) : '';
$name = htmlentities($name);
if ( $success ) {
header('location: next-step.php');
exit;
}
?>
<form action="" method="post">
<input type="name" value="<?php echo $name; ?>" name="name" placeholder="Your Name" />
<input type="button" name="submit" value="submit form "/>
</form>
<?php
if ( $errorMessage ) {
echo "<p>$errorMessage</p>";
}
?>
form engine repairs
You should also rectify your form_engine.php as per my comments above and Shekhar Joshi's answer, although I would keep the header code outside of your engine logic, and leave that decision to the code that requires in the engine — as the above does.
may be, you are looking for this! the header() method.
$success = true;
$errorMessage = " ";
$name = $_POST['name'];
if(isset($_POST['name'])) {
if ( $_POST['name'] == '') {
$errorMessage = 'Please enter your name';
$success = false;
header('Location: www.something.com/some.php');
}
else if ($success == true) {
// do something with the data
}
}
I want to use back option on php without losing the form data.
I've tried this way;
if ($username==""){
echo 'Please fill. <input type="button" value="Back" onClick="history.back()">';
} else{
$doaction;
}
And this way;
$url= $_SERVER['HTTP_REFERER'];
if ($username==""){
echo "Please fill.";
header("refresh: 2; url=$url");
}
else{
$doaction;
}
On both ways I lose my data. How can I make this better?
This worked for me and using ob_start(); (in PHP below) needs to be included, otherwise it will throw an error, such as:
PHP Warning: Cannot modify header information - headers already sent by (output started)
Use the following exactly as shown, then modify to suit later.
Using Sessions is a way to achieve this. Each field will re-appear in the input boxes, if they were filled.
HTML form (form.php)
<?php
session_start();
?>
<form method="post" action="submitted.php">
<p>
<label for='name'>Your Name:</label>
<br>
<input type="text" name="username" value="<?php echo isset($_SESSION['username']) ? $_SESSION['username'] : '' ?>">
</p>
<p>
<label for='name'>Email:</label>
<br>
<input type="text" name="email" value="<?php echo isset($_SESSION['email']) ? $_SESSION['email'] : '' ?>">
</p>
<input type="submit" name="submit" value="Submit">
<br>
</form>
PHP (submitted.php)
<?php
ob_start();
session_start();
$_SESSION['username'] = $_POST['username'];
$_SESSION['email'] = $_POST['email'];
$url= $_SERVER['HTTP_REFERER'];
$username=$_POST['username'];
$email=$_POST['email'];
// use this one below, if you want to check more than one field
// if (empty($_POST['username']) || empty($_POST['email']) ){
if (empty($_POST['username'])){
echo "Fill in all fields.";
header("refresh: 2; url=$url");
}
else{
echo "OK, redirecting back to show fields are showing, or not.";
header("refresh: 2; url=$url");
}
Your approach reloads the formular, so the webserver will send a clean form to the client. If you want a prefilled form you will have to use a PHP script which knows the formerly filled in values and creates a prefilled form.
In the code you have used, (assuming you have a form further up) there is no data being passed between the pages because nothing is telling the script to transfer the data between that page and it's destination.
In your first example, history.back() simply tells the browser to go back to the last page viewed before the current one. In your second example, your header line essentially just tells the browser to go back to the previous page after two seconds.
To keep data between page transfers, without any further knowledge of what you're doing, I would suggest using JavaScript to fetch your form data and pass it into a URL used in a window.location call (forming a GET request with your form data in it), OR by using javascript to set a cookie containing the data input before you tell the browser to switch page.
In the first solution, you could then use php's $_GET global to access your form data.
In the second solution, you could use javascript to re-populate the form on page load (or at will)
I'm still new and trying to learn php. I have a form and everytime I run it I get an error displaying that the variable were not set when they should be. I'm definately missing something. Kindly explain what why is the variable $_POST['login_button'] not set the first time i run the page?
Code can be found below:
<?php
require 'connect.inc.php';
if (isset($_POST['login_button']) && isset($_POST['username']) && isset($_POST['password'])){
$login_button = $_POST['login_button'];
$username = $_POST['username'] ;
$password = $_POST['password'];
$password_hash = md5($_POST['password']);
if(!empty($username)&&!empty($password)){
$sql = "SELECT `id` FROM `golden_acres_username` WHERE `uname`='$username' AND '".$password_hash."'";
if($sql_run = mysql_query($sql)){
$query_num_rows = mysql_num_rows($sql_run);
}
if($query_num_rows==0){
echo'User name and password are incorrect';
}
else if($query_num_rows==1)
{
echo 'Username and password are correct';
}
}
else
{
echo 'Please fill in user name and password';
}
}
else
{
echo'Fields are not set';
}
?>
<form class="home_logon_area" action="test.php" method="POST">
Username:
<input type="text" name="username" />
Password:
<input type="password" type="password" name="password"/>
<input type="submit" name="login_button">
</form>
Thanks in advance,
Joseph
$_POST contains the result of submitting a form. If no form has been submitted yet, it will not contain anything.
Your script is working just fine; remove echo 'Fields are not set';, or use that line for code that should only run when the form hasn't been submitted yet.
The $_POST variable is set by the server to capture the data content sent by the browser as part of the form POST action. When the page is initially loaded, the browser has only executed/requested a GET call for the content of the page without sending the POST request.
Hope that helps!
This is simple to understand ;-)
First time the phpscript is executed to get the Form
So there will be no information at all (the visitor is new and have not seen the form before)
Then the User fills the form and press Submit button
The form is linked to the same side so the same phpscript gets executed again
Now you have the Formular values transmitted and you can acess them over $_POST
For more information look at php.net
Remove last else from your code and update the form with this one
<form class="home_logon_area" action="test.php" method="POST">
Username:
<input type="text" name="username" required />
Password:
<input type="password" type="password" name="password" required/>
<input type="submit" name="login_button">
</form>