• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 355
  • Last Modified:

prevent multi form post

I'm trying to prevent a multi form post but don't seem like I've got it.


<?php
$domainName = $_SERVER['HTTP_HOST'];
$voucherCode = $_GET['v'];
if($voucherCode == "")
{
header("location:index.php");
}
//declare variable and set to empty
$message = "";
//db settings
$host="local"; // Host name 
$username="admin"; // Mysql username 
$password="admin!"; // Mysql password 
$db_name="dbtest"; // Database name 
$tbl_name="vouchers"; // Table name 
//get postback
if(isset($_POST['btnSubmit']))
{
	//get form data and clean it
    $firstName = check_input($_POST['txtbxfirstName']);
    $lastName = check_input($_POST['txtbxlastName']);
    $address1 = check_input($_POST['txtbxaddress1']);
    $address2 = $_POST['txtbxaddress1'];
    if($address2 != "")
    {
    	$address2 = check_input($_POST['txtbxaddress2']);
    }
    $city = check_input($_POST['txtbxcity']);
    $state = check_input($_POST['ddlstate']);
    $zip = check_input($_POST['txtbxzip']);
	$phone = check_input($_POST['txtbxprimaryphone']);
	$email = check_input($_POST['txtbxemailaddress']);
	$vouchercode = $_POST['hvvc'];
	$dateredeemed = date("m/d/y",time());
	
    //search for the value and if redeemed
    searchTable($vouchercode);
	//load data
	loadData($firstName,$lastName,$address1,$address2,$city,$state,$zip,$phone,$email,$vouchercode,$dateredeemed,$domainName);	
}
//run process to clean form data
function check_input($data)
{
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}
//search for data
function searchTable($data)
{
	//global variables
	global $message,$host, $username, $password,$db_name,$tbl_name;

	mysql_connect("$host", "$username", "$password")or die("cannot connect ".mysql_error()); 
	mysql_select_db("$db_name")or die("cannot select DB - ".mysql_error()); 
	$query = "select vouchercode from $tbl_name where vouchercode = '$data' ";
	$result = mysql_query($query)or die(mysql_error());
	if (mysql_num_rows($result))
	{
	    //$message = "This is voucher has been redeemed.";
	    header("location:index.php");
	}
}
//load data
function loadData($firstName,$lastName,$address1,$address2,$city,$state,$zip,$phone,$email,$vouchercode,$dateredeemed,$domainName)
{
	//global variables
	global $domainName, $message, $host, $username, $password,$db_name,$tbl_name;
	mysql_connect("$host", "$username", "$password")or die("cannot connect ".mysql_error()); 
	mysql_select_db("$db_name")or die("cannot select DB - ".mysql_error());

	try
	{
		mysql_query("insert into $tbl_name (firstname,lastname,address1,address2,city,state,zip,primaryphone,emailaddress,vouchercode,dateredeemed,domain) values ('$firstName','$lastName','$address1','$address2','$city','$state','$zip','$phone','$email','$vouchercode','$dateredeemed','$domainName')");
	}
	catch (Exception $e)
	{
		header("location:error.php");
	}
	
	try
	{
		mysql_query("update vouchercodes set redeemed = 'Y' where vouchercode = '$vouchercode'");
	}
	catch (Exception $e)
	{
		header("location:error.php");
	}
	
	$message = "Your voucher has been entered into our systems and is pending review. Thank you.";
	header("location:thankyou.php?fn=$firstName&ln=$lastName&msg=$message");
}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Untitled 1</title>
<script type="text/javascript">
//validate the form
function ValidateForm()
{
	//validate txtbxfirstName
	if(document.vcodeform.txtbxfirstName.value == "")
   	{ 
    	alert('You must indicate your first name.') 
      	document.vcodeform.txtbxfirstName.focus(); 
      	return false; 
   	}
   	//validate txtbxlastName
	if(document.vcodeform.txtbxlastName.value == "")
   	{ 
    	alert('You must indicate your last name.') 
      	document.vcodeform.txtbxlastName.focus(); 
      	return false; 
   	}
   	//validate txtbxaddress1
	if(document.vcodeform.txtbxaddress1.value == "")
   	{ 
    	alert('You must indicate your address 1.') 
      	document.vcodeform.txtbxaddress1.focus(); 
      	return false; 
   	}
   	//validate txtbxaddress2
	//if(document.vcodeform.txtbxaddress2.value == "")
   	//{ 
    	//alert('You must indicate your address 2.') 
      	//document.vcodeform.txtbxaddress2.focus(); 
      	//return false; 
   	//}
   	//validate txtbxcity
	if(document.vcodeform.txtbxcity.value == "")
   	{ 
    	alert('You must indicate your city.') 
      	document.vcodeform.txtbxcity.focus(); 
      	return false; 
   	}
	//validate txtbxzip
	if(document.vcodeform.txtbxzip.value != "")
   	{
		if(checkZip(document.vcodeform.txtbxzip.value))
	   	{
			  // 
	   	}
	   	else
	   	{
		  	alert('Your Zip Code is in an incorrect format.') 
		  	document.vcodeform.txtbxzip.focus(); 
		  	return false; 
	   	}
   	}
   	else
   	{ 
      	alert('You must indicate your Zip Code.') 
      	document.vcodeform.txtbxzip.focus(); 
      	return false; 
   	}
	//valiate txtbxprimaryphone
	if(document.vcodeform.txtbxprimaryphone.value != "")
   	{ 
   		if (checkPhone(document.vcodeform.txtbxprimaryphone.value))
		{
			//
		}
		else
		{
			alert('Your Phone Number is in an incorrect format.') 
			document.vcodeform.txtbxprimaryphone.focus(); 
			return false;   
		}
   	}
   	else
   	{
		if(document.vcodeform.txtbxprimaryphone.value == "")
		   	{
		      	alert('You must indicate your Phone Number.') 
		      	document.vcodeform.txtbxprimaryphone.focus(); 
		      	return false; 
		   	}
	}
	//validate txtbxemailaddress
   	if(document.vcodeform.txtbxemailaddress.value != "")
   	{
		if(checkEmail(document.vcodeform.txtbxemailaddress.value))
	   	{
		  // 
	   	}
	   	else
	   	{
      		alert('Your Email Address is in an incorrect format.') 
      		document.vcodeform.txtbxemailaddress.focus(); 
      		return false; 
	   	}
   	}
   	else
   	{
		if(document.vcodeform.txtbxemailaddress.value == "")
	   	{ 
			alert('You must indicate your Email Address.') 
	      	document.vcodeform.txtbxemailaddress.focus(); 
	      	return false; 
	   	}
	}
//end
return true; 
}
//validate zip code
function checkZip(str) 
{
	var zip2 = /^\d{5}$/; 
	if (str.match(zip2)) {
   		return true;
 	} else {
 		return false;
 	}
}
//validate phone format
function checkPhone(str) 
{
	var phone2 = /^(\+\d)*\s*(\(\d{3}\)\s*)*\d{3}(-{0,1}|\s{0,1})\d{2}(-{0,1}|\s{0,1})\d{2}$/; 
	if (str.match(phone2)) {
   		return true;
 	} else {
 		return false;
 	}
}
//validate email format
function checkEmail(str) 
{
	var email2 = /^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/; 
	if (str.match(email2)) {
   		return true;
 	} else {
 		return false;
 	}
}
</script>
</head>
<body onload="document.vcodeform.txtbxfirstName.focus();">
<form name="vcodeform" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
 <table cellpadding="0" cellspacing="0" style="width: 25%">
	<tr>
		<td colspan="2">Redeem your Voucher</td>
	</tr>
	<tr>
		<td colspan="2">Voucher Code: <?php echo $voucherCode; ?></td>
	</tr>
	<tr>
		<td>First Name</td>
		<td><input name="txtbxfirstName" type="text" id="txtbxfirstName" tabindex="1"></td>
	</tr>
	<tr>
		<td>Last Name</td>
		<td><input name="txtbxlastName" type="text" id="txtbxlastName" tabindex="2"></td>
	</tr>
	<tr>
		<td>Address 1</td>
		<td><input name="txtbxaddress1" type="text" id="txtbxaddress1" tabindex="3"></td>
	</tr>
	<tr>
		<td>Address 2</td>
		<td><input name="txtbxaddress2" type="text" id="txtbxaddress2" tabindex="4"></td>
	</tr>
	<tr>
		<td>City</td>
		<td><input name="txtbxcity" type="text" id="txtbxcity" tabindex="5"></td>
	</tr>
	<tr>
		<td>State</td>
		<td>
		<select name="ddlstate" size="1" tabindex="6">
        <option value="AK">AK</option>
        <option value="AL">AL</option>
        <option value="AR">AR</option>
        <option value="AZ">AZ</option>
        <option value="CA">CA</option>
        <option value="CO">CO</option>
        <option value="CT">CT</option>
        <option value="DC">DC</option>
        <option value="DE">DE</option>
        <option value="FL">FL</option>
        <option value="GA">GA</option>
        <option value="HI">HI</option>
        <option value="IA">IA</option>
        <option value="ID">ID</option>
        <option value="IL">IL</option>
        <option value="IN">IN</option>
        <option value="KS">KS</option>
        <option value="KY">KY</option>
        <option value="LA">LA</option>
        <option value="MA">MA</option>
        <option value="MD">MD</option>
        <option value="ME">ME</option>
        <option value="MI">MI</option>
        <option value="MN">MN</option>
        <option value="MO">MO</option>
        <option value="MS">MS</option>
        <option value="MT">MT</option>
        <option value="NC">NC</option>
        <option value="ND">ND</option>
        <option value="NE">NE</option>
        <option value="NH">NH</option>
        <option value="NJ">NJ</option>
        <option value="NM">NM</option>
        <option value="NV">NV</option>
        <option value="NY">NY</option>
        <option value="OH">OH</option>
        <option value="OK">OK</option>
        <option value="OR">OR</option>
        <option value="PA">PA</option>
        <option value="RI">RI</option>
        <option value="SC">SC</option>
        <option value="SD">SD</option>
        <option value="TN">TN</option>
        <option value="TX">TX</option>
        <option value="UT">UT</option>
        <option value="VA">VA</option>
        <option value="VT">VT</option>
        <option value="WA">WA</option>
        <option value="WI">WI</option>
        <option value="WV">WV</option>
        <option value="WY">WY</option>
        </select>
		</td>
	</tr>
	<tr>
		<td>Zip</td>
		<td><input name="txtbxzip" type="text" id="txtbxzip" tabindex="7"> Ex: xxxxx</td>
	</tr>
	<tr>
		<td>Primary Phone</td>
		<td><input name="txtbxprimaryphone" type="text" id="txtbxprimaryphone" tabindex="8"> Ex: (xxx) xxx-xxxx</td>
	</tr>
	<tr>
		<td>Email Address</td>
		<td><input name="txtbxemailaddress" type="text" id="txtbxemailaddress" tabindex="9"> Ex: xxx@xxx</td>
	</tr>
	<tr>
		<td colspan="2">
		<input name="btnSubmit" type="submit"  id="btnSubmit" onclick="return ValidateForm()" value="Submit" tabindex="10">
		<input type="hidden" id="hvvc" name="hvvc" value="<?php echo $voucherCode; ?>" />
		</td>
	</tr>
	<tr>
		<td colspan="2">
				<?php 
		  //print form data
		      echo $message; 
		?>
		</td>
	</tr>
</table>
</form>
 </body>

</html>

Open in new window

0
vicomin
Asked:
vicomin
  • 4
  • 3
1 Solution
 
Ray PaseurCommented:
Wow, over 300 lines of code for us to sift through...

Can you please restate the question and tell us what you mean by multi form post?  Thanks, ~Ray
0
 
Mohamed AbowardaSoftware EngineerCommented:
In javascript, create public boolean, when the user submit the form set it to TRUE, you can do that by changing form onsubmit.

Everytime the user submit the form, check if the variable is FALSE, if not ignore the submit request, there is already one in progress.
0
 
Ray PaseurCommented:
If the problem definition is what I think it might be (client submits the form twice with the same data) I think I might want to do the validation on the server side of things.  Clients can, and do, turn off JavaScript.  Hackers can, and do, post toxic stuff directly into action scripts.  For that reason alone, most security experts advise that any client-side security measure is essentially meaningless and must be handled on the server.  That is not to say that client-side data validation has no place in web design.  On the contrary, it may make for very nice forms.  But you will still have to validate all of the information after you get it on the server and it is completely outside of the client's hands.

In any case, when the author of the question answers what is meant by "multi form post?" we will be better equipped to produce a good answer and an example of a script that can be adapted to suit the needs.
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
Mohamed AbowardaSoftware EngineerCommented:
@Ray_Paseur: You just understood the question from my solution! :)
0
 
Ray PaseurCommented:
just understood the question - Yes, that may be true!  Here is how I have dealt with the issue in the past.  Example available on my server here:
http://www.laprbass.com/RAY_multi_submit.php
<?php // RAY_multi_submit.php
error_reporting(E_ALL);


// PREVENT MULTIPLE SUBMISSIONS DUE TO REPEATED CLICKS ON SUBMIT BUTTON
// EXAMPLE:
//    if ( multi_submit() )
//    {
//       handle error
//    }
//    else
//    {
//       normal processing
//    }



// ALWAYS START SESSION ON EVERY PAGE
session_start();


function multi_submit($type="post")
{
    // MAKE THE FUNCTION WORK FOR EITHER GET OR POST SUBMITS
    $input_array = (strtoupper($type) == "GET") ? $_GET : $_POST;

    // GATHER THE CONTENTS OF ALL THE SUBMITTED FIELDS AND MAKE A MESSAGE DIGEST
    $string = "";
    foreach ($input_array as $val) { $string .= $val; }
    $string = md5($string);

    // IF THE SESSION VARIABLE IS NOT SET, THIS IS NOT A MULTI-SUBMIT
    if (!isset($_SESSION["_multi_submit"]))
    {
        // SAVE THE SUBMITTED DATA MESSAGE DIGEST
        $_SESSION['_multi_submit'] = $string;
        return FALSE;
    }

    // IF THE SESSION DATA MATCHES THE MESSAGE DIGEST, THIS IS A MULTI-SUBMIT
    if ($_SESSION['_multi_submit'] === $string)
    {
        return TRUE;
    }
    else
    {
        // SAVE THE MESSAGE DIGEST
        $_SESSION['_multi_submit'] = $string;
        return FALSE;
    }
}

// SHOW HOW THIS IS DONE
if (!empty($_POST))
{
    if (multi_submit())
    {
        die("ALREADY GOT THAT");
    }
}
// END OF PHP - PUT UP THE FORM
?>
<form method="post">
ENTER SOMETHING, THEN REENTER IT
<input name="foo" />
<input type="submit">
</form>

Open in new window

0
 
vicominAuthor Commented:
multi - meaning that the user resubmits the web form -- send once okay but more than once is what i want to prevent -- guess that is double post?
0
 
Mohamed AbowardaSoftware EngineerCommented:
In Experts Exchange, when you submit a question/comment, the "submit" button only accept the first click, if you double clicked, it will ignore the second click, and you can exactly do the same by using boolean which will check whether the button already clicked or not.

Look at my initial post, it should help you with you are trying to do.

You can also do some server side coding to prevent that by adding random hash key generated on page load by PHP, the hash key will be sent on submit by hidden input inside the form as the following:
<input type="hidden" name="formHash" value="THE_RANDOM_HASH_KEY_WILL_BE_HERE">

Open in new window


This hash key will be stored into session each time the user submit the form.

Each time the server receive the form, it will check if the hash is the same as the last one, in the case that the user submitted the form twice, the hash key will be submitted twice also, so the server will know that this is duplication and ignore the duplication request as the first request is still progress.
0
 
Ray PaseurCommented:
... the user resubmits the web form -- send once okay but more than once is what i want to prevent
The discussion and code example at ID:35694830 shows exactly how to do this.  I use it all the time in my own web sites.  You do not need to add any hash key to the form; the hash is made from the submitted data, as shown in lines 27-30 of the demonstration script.

You cannot really prevent the client machine from resubmitting a form, any more than you can prevent hackers from attacking your action script, but you can detect duplicate submissions and you can filter the input data.  Both of those are important in online applications where, from a security perspective, all external input must be considered to be an attack vector.  As the security mantra goes, "Accept Only Known Good Values."

Anyway, thanks for clarifying the question.  You can test that script on my server or install it and run it on your own server to see how it implements the solution.  Best regards, ~Ray
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now