I have a problem with my PHP script, which checks 3 variables (code below):
$auth (The mail author)
$subj (The mail subject)
$text (The mail message)
FORM:
(NOTE: I used the "GET" method because for some strange reason the "POST" method didn't work)
<div id="contact_form">
<form method="get" name="contact" action="home.php">
<input type="hidden"
name="method"
value="send"/>
E-Mail:<br/>
<input type="text"
id="author"
name="author"
class="require input_field"
value=""/>
<br/>
Subject:<br/>
<input type="text"
id="subject"
name="subject"
class="require input_field"
value=""/>
<br/>
Message:<br/>
<textarea id="text"
name="text"
rows="0"
cols="0"
class="required"
value=""></textarea>
<br/>
<input type="submit"
class="submit_btn"
name="submit"
id="submit"
value="Submit" />
</form>
</div>
The form works just fine now.
PHP:
<?php // ||HOME.PHP||
$method = $_GET['method'];
$auth = $_GET['author'];
$subj = $_GET['subject'];
$text = $_GET['text'];
$recv = "mymail#stuff.com";
function redirect($location) {
if($location == "true") {
header("Location: http://mysite.com/home.php?method=result&status=true");
} else {
header("Location: http://mysite.com/home.php?method=result&status=false");
}
}
//...
//Other methods...
//...
//METHOD SEND
if($method == "send") {
//HERE IS THE PROBLEM
//These are apparently not working
//If i leave the form blank and submit it
//these won't redirect to "false" (mail not sent),
//and the script will just continue, send the empty mail
//and redirect to "true" (mail sent)
if(empty($auth)) { redirect(""); }
if(empty($subj)) { redirect(""); }
if(empty($text)) { redirect(""); }
if(!strstr($auth, '#')) { redirect(""); }
if(!strstr($auth, '.')) { redirect(""); }
if(strlen($auth) < 5) { redirect(""); }
if(strlen($subj) < 4) { redirect(""); }
if(strlen($text) < 4) { redirect(""); }
//From here it should work just fine
//As i'm not sure the "RESULT" method (below) is working fine, i
//posted it too.
$auth = "From: " . $auth;
mail($recv,$subj,$text,$auth);
redirect("true");
require("template/footer.html");
exit(0);
}
//METHOD RESULT
if($method == "result") {
$status = $_GET['status'];
if($status == "true") {
echo "mail sent";
} else {
echo "mail not sent";
}
?>
<script language="javascript">
setTimeout("location.href = 'http://adteam.altervista.org/home.php';", 5000);
</script>
<?php
exit(0);
} ?>
The problem is explained in the PHP code (in the comments below the "SEND" method).
Do you guys have any suggestion?
You need to stop the script execution after you've set the redirect headers. Otherwise it will just continue to sending the mail and set new redirect headers before any headers are sent to the browser.
function redirect($location) {
if($location) {
header("Location: http://mysite.com/home.php?method=result&status=true");
} else {
header("Location: http://mysite.com/home.php?method=result&status=false");
}
die();
}
Note that if( $location == "true" ) is kind of an anti-pattern; it's better to use boolean true and false instead of strings.
Should be easy. Your saying that "" is false. But it ain't: because "" is true, but empty which is true. false is not set or specified false. So you should do:
function redirect($location) {
if($location) {
header("Location: http://mysite.com/home.php?method=result&status=true");
exit();
} else {
header("Location: http://mysite.com/home.php?method=result&status=false");
exit();
}
}
And use: redirect(true) / redirect(false);
A string will always evaluate to true, even if it is empty. That's precisely the reason why we check strings using empty() as opposed to isset(). A few more things:
You should be using POST to submit the email.
You should probably check if the form was actually submitted before validating the input.
You should create and display specific error messages telling the user what required fields they did not complete.
You should run some careful validation routines on the input to avoid having your email form used to send spam and malware.
Simply add exit in false branch:
function redirect($location) {
if($location == "true") {
header("Location: http://mysite.com/home.php?method=result&status=true");
} else {
header("Location: http://mysite.com/home.php?method=result&status=false");
exit(0); //simply add it here
}
}
header function does not stop further execution by itself and you must stop doing anything else if do not want to send an email when something is wrong.
Actually, you may simply add exit after if statement.
Related
I am trying to validate my RSVP form using only PHP. The user should receive an error message when the form is incomplete. I am trying to avoid the use of jQuery.
I am using this tutorial:
http://premium.wpmudev.org/blog/how-to-build-your-own-wordpress-contact-form-and-why/
The form is functioning fine but I haven't been able to get the error messages to display at all. I am using Wordpress and I want the form to appear at the footer of every page; not sure if this complicates matters. Here is my code:
<?php
$response = "";
//function to generate response
function my_contact_form_generate_response($type, $message) {
global $response;
if ($type == "success") {
$response = "<div class='success'>{$message}</div>";
} else {
$response = "<div class='error'>{$message}</div>";
}
}
//response messages
$missing_content = "Please supply all information.";
$email_invalid = "Email Address Invalid.";
$message_unsent = "Message was not sent. Try Again.";
$message_sent = "Thanks! Your message has been sent.";
//variables defined for messages
$email = $_POST["rsvp_email"];
$name = $_POST["rsvp_name"];
$attend = $_POST["rsvp_attend"];
$number = $_POST["rsvp_number"];
//variables defined for message to admin
$to = get_option('admin_email'); //sending to wordpress admin email
$subject = "Just Kidding You Foo";
$headers = "From: $email\n";
$message = "$name $attend.\n RSVPs $number of people";
//conditional statements used for form validation
//validate email
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
my_contact_form_generate_response("error", $email_invalid);
} else { //email is valid
//validate presence of name and message
if(empty($name) || empty($attend) || empty($number)) {
my_contact_form_generate_response("error", $missing_content);
} else { //ready to go!
$sent = wp_mail($to,$subject,$message,$headers);
if($sent) {
my_contact_form_generate_response("success", $message_sent); //message sent!
} else {
my_contact_form_generate_response("error", $message_unsent); //message wasn't sent
}
}
}
?>
<div id="page-rsvp">
<h1>RSVP</h1>
<div id="respond">
<?php echo $response; ?>
<form action="<?php the_permalink(); ?>" method="post">
<!--Name here-->
<div class="rsvp-full"><label for="rsvp_name"><input type="text" name="rsvp_name" value="Your name"></label></div>
<div class="rsvp-full"><label for="rsvp_email"><input type="text" name="rsvp_email" value="Your email"></label></div>
<!--status of attendance-->
<div class="rsvp-full">
<div class="rsvp-element"><input id="radio-button" type="radio" name="rsvp_attend" value="accepts">Accepts</div>
<div class="rsvp-element"><input id="radio-button" type="radio" name="rsvp_attend" value="declines">Declines</div>
</div>
<!--number of guests attending-->
<div class="rsvp-full"><input type="number" name="rsvp_number" min="1" max="5">Total number of guests attending</div>
<div id="submit-button" class="rsvp-full"><input id="submit-button" type="submit"></div>
</form>
</div>
</div>
TIA!!!
I'm not that familiar with WP, but if I understand correctly, I believe you're trying to ensure all the fields are filled out.
Check your brackets! You need to be sure your curly brackets are opening and closing where you want them to. Otherwise the output of the page won't display. I write in all my braces because I'm not smart enough to be sure I know where they start and stop. I've taken the liberty of editing them into your question. I believe there was one missing at the end.
Once I fixed the brackets and removed functions my computer didn't have, it worked fine.
Tip 0: Try turning error reporting on for this script - error_reporting(E_ALL); at the top of this script. I always do for development.
Tip 1: use the placeholder attribute instead of value for things like "your name".
Tip 2: make sure the $_POST vars are set. I would do this by checking if they're set and then setting them to '' if they aren't; something like this:
//variables defined for messages
// you could do it like this:
if (isset($_POST["rsvp_email"])) {
$email = $_POST["rsvp_email"];
} else {
$email = '';
}
// or like this:
$name = '';
if (isset($_POST["rsvp_name"])) {
$name = $_POST["rsvp_name"];
}
// or even using a ternary operator:
$attend = isset($_POST["rsvp_attend"]) ? $_POST["rsvp_attend"] : '';
//but this will trigger a "Notice" error if the post var isn't set.
$number = $_POST["rsvp_number"];
I'm trying to implement a simple CSRF protection on a form, but I can't get it right. If someone can point out what I'm doing wrong, I would appreciate it.
The error: Every time I submit the form, I get "Invalid Submission2" because the token changes (after the form is submitted), since is being generated on the same page?
Edit -- I forgot to mention, another file (config.php) already has session_start().
<?php
class Module_Post extends Base_Module {
public function start()
{
requireLogin();
if (isset($_GET['act'])) {
switch($_GET['act']) {
case 'text':
$this->text();
break;
case 'image':
$this->image();
break;
default:
$this->text();
break;
}
} else {
$this->text();
}
}
private function text()
{
// Generate random unique token to prevent cross-site request forgery (CSRF).
if(empty($_SESSION['form_token']))
{
$form_token = md5(uniqid(rand(), TRUE));
$_SESSION['form_token'] = $form_token;
}
if(isset($_POST['submit']))
{
// Clean the content from cross-site scripting (xss)
$content = trim($_POST['content']);
$content = Xss::clean($content);
// Validate that the form token
if(!isset($_POST['form_token'], $_SESSION['form_token'])) {
$err = 'Invalid Submission';
} elseif ($_POST['form_token'] != $_SESSION['form_token']) {
$err = 'Invalid Submission2';
} elseif (strlen($content) < 10) {
$err = 'Your content contains too few characters.';
}
if(isset($err)) {
unset( $_SESSION['form_token']);
$this->setMessage($err, 'FAIL');
header('Location: index.php?mod=post');
exit;
}
// Insert database data here, then redirect
$this->setMessage('Your post was published successfully.', 'GOOD');
header('Location: index.php');
exit;
}
$this->tpl->assign('form_token', $form_token);
$this->tpl->display('new/text.tpl');
}
}
?>
The HTML (text.tpl file)
<form method='post' enctype='multipart/form-data' action='#'>
<fieldset>
<textarea rows="8" id="new_post" name="content" class="input-block-level"></textarea>
<input type="hidden" name="form_token" value="{$form_token}" />
<button type="submit" name="submit" class="btn btn-info pull-left">Create Post</button>
</fieldset>
</form>
You need to change this line
$this->tpl->assign('form_token', $form_token);
into:
$this->tpl->assign('form_token', $_SESSION['form_token']);
That's because you generate your token only with this condition:
if(empty($_SESSION['form_token']))
{
$form_token = md5(uniqid(rand(), TRUE));
$_SESSION['form_token'] = $form_token;
}
and unset it using this condition:
if(isset($err)) {
unset( $_SESSION['form_token']);
}
So if you send your form once and then reload page (without submitting form just url), $form_token variable is unknown because there is $_SESSION['form_token'] is not empty and then in your form you have empty token.
If you had displaying errors turned on in PHP you would see in this case in PHP:
Undefined variable: form_token in
I am trying to wrap up this contact/quote form which has same page validation but external processing. I have set up a variable to go in the form action and the variable/url changes from the same page to the processing page when the form validates. However, it is taking two clicks on the submit button to process the form after all the required fields have been filled in: All the required fields will be filled in, I click submit, the page reloads with the saved data variables and then when I hit submit agin, it finally goes through, sending the email and loading the thankyou page. I have searched the posts here and tried multiple things but have not found a solution. I am definitely not a php expert, still a newbie so this may not be the best way to accomplish this but I'd appreciate any ideas on how to finish this up. Here is what I have:
<?php
....
if (empty($Name) && empty($Company) && empty($Address1) && empty($City) && empty($State) && empty($Phone))
{
echo '<p class="tan">The fields marked with an * are required.</p>';
$Process = 'samepageurl';
}
/*else if (empty($Name) || is_numeric($Name))
{
echo '<p class="tan"><b>Please enter your name.</b></p>';
}*/
else if (empty($Company) || is_numeric($Company))
{
echo '<p class="tan"><b>Please enter your company name.</b></p>';
$Process = 'samepageurl';
}
else if (empty($Address1) || is_numeric($Address1))
{
echo '<p class="tan"><b>Please enter your address.</b></p>';
$Process = 'samepageurl';
}
else if (empty($City) || is_numeric($City))
{
echo '<p class="tan"><b>Please enter your city.</b></p>';
$Process = 'samepageurl';
}
else if (empty($State) || is_numeric($State))
{
echo '<p class="tan"><b>Please enter your state.</b></p>';
$Process = 'samepageurl';
}
else if (empty($Phone) || ctype_alpha($Phone))
{
echo '<p class="tan"><b>Please enter your phone number.</b></p>';
$Process = 'samepageurl';
}
else if (strlen($Phone) < 10 || strlen($Phone) > 12 || ctype_alpha($Phone) || ctype_space($Phone))
{
echo '<p class="tan"><b>Please enter a phone number with an area code.</b></p>';
$Process = 'samepageurl';
}
else if (isset($Name) && isset($Company) && isset($Address1) && isset($City) && isset($State) && isset($Phone))
{
$Process = 'processingurl';
}
?>
<form action="<?php echo $Process; ?>" method="post" class="print" >
<p><input type="hidden" name="recipient" value="responses#url.com"/>
<input type="hidden" name="subject" value="Web Site Response"/>
<input type="hidden" name="redirect" value="thankyou.html"/></p>
... form fields ...
</form>
Thank you in advance!
First check for missing variables, then extract and validate the variables, then serve content based on them.
<?php
function verifyPostContains(&$req) {
global $_POST;
$missing = array();
foreach($req as $var => $_) {
if(!isset($_POST[$var])) {
$missing[] = $var;
}
}
return $missing;
}
$requirements = array('name'=>'','city'=>'','state'=>'',...);
$missing = verifyPostContains($requirements);
if(count($missing)>0) {
$content = formErrorReport($missing);
sendHeaders();
echo $content;
exit();
}
// extract, making sure to sanitize
$name = sanitize($_POST["name"]);
...
$errorHtml = array();
// validate by reference. Effectively call testName($name).
if(failsValidation($name, "testName")) {
$errorHtml [] = generateError(NAME_ERROR, $name);
} else { $requirements["name"] = $name; }
if(failsValidation($city, "testCity")) {
$errorHtml [] = generateError(CITY_ERROR, $city);
} else { $requirements["city"] = $name; }
...
if(count($errorHTML)>0) {
generateErrorPage($requirements, $missing, $errorHTML);
} else { processForm($requirements); }
?>
this code assumes you have functions to do the various bits that need to be done, and has some string constants for generating error HTML.
As a newcomer you may want to google for some tutorials that explain doing form processing using PHP at the server, and JavaScript at the client. If you find a tutorial that gives you code that echos errors while it's testing the data, such as you code does, move along. It's not a good tutorial. If you find one that stops after it finds one error, move along too. If you find one that tells you to make sure the values are right in JavaScript, and then says "we already validated this at the client so we use the values directly in PHP", move along, too. Look for a tutorial that explains:
ensuring there's data in all the form fields, using JavaScript, so the submit button is disabled until there's data for all the fields.
ensuring the data matches your criteria, in PHP, so that people who just POST to your server without ever using your page don't get away with injecting all manner of fun stuff they weren't supposed to be able to do
you generate a page with all the errors explained, if there are any, and the form repopulated with the wrong data, but highlighted as wrong
you process the post request if there are no errors.
(Bonus points if the tutorial explains that a POST request is not required to actually ever generate page content as a response, other than a header that indicates whether or not the POST call was accepted or rejected.)
I have coded some alerting system.
But let's not look at the system itself, Let's look at how will the system know that the system really did sent the alert/error to the browsing user.
I have made something so when you randomly go to ?alert=name, without doing any error, it will say 'No errors'.
But if the system makes you go to ?alert=name, it will echo the error.
How I handle posts
function postComment() {
if (!empty($_POST['name']) || !empty($_POST['comment'])) {
$comment = mysql_real_escape_string(htmlentities($_POST['comment']));
$guest = mysql_real_escape_string(htmlentities($_POST['name']));
}
$guestId = 1;
if (empty($guest)) {
$alert = 1;
return header('location: index.php?alert=name');
}
if (empty($comment)) {
$alert = 2;
return header('location: index.php?alert=comment');
}
if (!isset($_COOKIE['alreadyPosted'])) {
mysql_query("INSERT INTO `comments` (`comment_guest`, `guest_id`, `comment`, `comment_date`, `comment_time`) VALUES ('$guest', '$guestId', '$comment', CURDATE(), CURTIME())") or die(mysql_error());
header('Location: index.php?action=sucess');
setcookie(alreadyPosted, $cookieId+1, time() + 60);
} else {
$alert = 3;
header('location: index.php?alert=delay');
}
}
As you see, to check if user really getting that error, I will set $alert to whatever error number it is.
And to check if hes getting the error I will use this:
if (isset($_GET['alert']) == 'name') {
if ($alert == 1) {
echo 'hai';
} else {
echo 'No errors';
}
}
You will probably wonder why I am doing it this way.., well because I use 1 function for post, and my post function goes under the form, and i want the alerts to display up to the form.
Problem:
The variable either doesn't get set to the number that it is supposed to when running the function,
or.. something is blocking it from it.. I don't know..
My guess: Because the check for errors is located up to the postComment function before the variables even get set?
<?php
if (isset($_GET['alert']) == 'name') {
if ($alert == 1) {
echo 'hai';
} else {
echo 'No errors';
}
}
?>
<form action="index.php" method="POST">
<input type="text" name="name" placeholder="Your name here" class="field">
<textarea class="textarea" name="comment" placeholder="Your comment here..."></textarea>
<input type="submit" name="send" class="blue_button" value="Post Comment">
</form><input type="submit" name="" id="margin" class="blue_button" value="See all messages">
<br />
<?php
//Show the comments
showComments();
if (isset($_POST['send'])) {
postComment();
}
if (isset($_GET['delete']) == "comment"){
deleteComment();
}
echo '<br />';
?>
If it is, what is the solution?
Thanks!
Please don't start with the story about mysql_ function, I understood & I will use PDO instead, but I am using mysql_ at the moment for testing purposes
The problem is that you're redirecting on an error, and so the $alert variable does not get carried over.
To fix the problem add the alert type to the $_GET parameters:
function postComment()
{
// ...
if (empty($guest))
{
header('location: index.php?alert=name&alert_type=1');
exit;
}
// ...
}
And then when you check for the error:
if (isset($_GET['alert']) && 'name' == $_GET['alert'])
{
if (isset($_GET['alert_type']) && '1' == $_GET['alert_type'])
{
echo 'hai';
}
else
{
echo 'No errors';
}
}
Note also that I fixed the error here:
isset($_GET['alert']) == 'name'
That doesn't do what I think you think it does. What you want is:
isset($_GET['alert']) && 'name' == $_GET['alert']
(Excuse the order of the comparison; I prefer to have variables on the right for comparisons as it will cause a parse error if you miss a = -- much better than having it run but not do what you expect)
if you are a newbie, you better consider using client side scripting (viz javascript) for validation as using server side validation will simple make the process longer. but as you are facing problems, this might give you the solution.
as you are redirecting the page to index.php?alert=name', so $alert is never set initially when the page loads itself. when you call the function postcomment(), $alert is initiated but immediately destroyed when the system redirects. And as $alert never holds a value when you randomly visit the page, it shows no error.
I have a system where the user sends an email using a form (simple).
HTML form
<form method="post" action="process.php">
<label class="fieldLabel">Your email:</label><label class="errorLabel"><?php echo $form->error("email"); ?></label>
<input type="text" name="email" maxlength="100" class="email" value="<?php echo $form->value("email"); ?>" />
<label class="fieldLabel">Your enquiry:</label><label class="errorLabel"><?php echo $form->error("body"); ?></label>
<textarea name="body" class="enquiry"><?php echo $form->value("body"); ?></textarea>
<input type="submit" name="enquiry" class="button" value="Send Message"/>
</form>
On the same page, I have this if statement
if(isset($_SESSION['enq'])){
if($_SESSION['enq']){
echo "<h2>Your message has successfully been sent to Alan Slough.</h2>";
}
else{
echo"<h2>Oops, something went wrong. Please try again.</h2>";
}
unset($_SESSION['enq']);
}
Now the process.php file the form directs to
class Process{
//class constructor
function Process(){
if(isset($_POST['enquiry'])){
$this->enquiry();
}
}
function enquiry(){
global $session, $form;
//Registration attempt
$retval = $session->enquiry($_POST['email'], $_POST['body']);
//Successful
if($retval == 0){
$_SESSION['enq'] = true;
header("Location: contact-us.php");
}
//Error found with form
else if($retval == 1){
$_SESSION['value_array'] = $_POST;
$_SESSION['error_array'] = $form->getErrorArray();
header("Location: contact-us.php");
}
//Failed
else if($retval == 2){
$_SESSION['enq'] = false;
header("Location: contact-us.php");
}
}
};
And now the session page where everything happens
//enquiry being made
function enquiry($email, $body){
global $form;
//check email entered
$field = "email";
if(!$email || strlen($email = trim($email)) == 0){
$form->setError($field, "* Not entered");
}
//check body(s) entered
$field = "body";
if(!$body || strlen($body = trim($body)) == 0){
$form->setError($field, "* Not entered");
}
//if errors exist, send them back to the user
if($form->num_errors > 0){
return 1; //errors with form
}
else if($form->num_errors == 0){
$this->customerEnquiry($email, $body);
return 0; //successful
}
else{
return 2; //failed
}
}
//send the enquiry to the account email
function customerEnquiry($email, $body){
$from = "From: ".$email." <".$email.">";
$to = "random#email.com";
$subject = "Website enquiry from ".$email."";
return mail($to,$subject,$body,$from);
}
Ok my problem is that the errors aren't coming back if I don't fill in the form. Also, the success text isn't being displayed if I don't?
Anyone see a problem with how this flows?
Hoping I have just missed something simple!
Thanks!
I noticed this bit of code.
if(isset($_SESSION['enq'])){ // <---This...
if($_SESSION['enq']){ // <---And This
echo "<h2>Your message has successfully been sent to Alan Slough.</h2>";
}
else{
echo"<h2>Oops, something went wrong. Please try again.</h2>";
}
unset($_SESSION['enq']);
}
If $_SESSION['enq'] is not set, then the IF statement inside that will never execute, meaning you will see neither the success nor failure message.
Also, are you starting the session anywhere on the page? If you never start a session, then $_SESSION['enq'] will never be set.
http://www.php.net/manual/en/function.session-start.php
This is a very strange way to go about this. For example you're displaying success/failure message before the e-mail has been sent.
Have you copy and pasted this?
The usual method to do this would be to have the logic in process.php only, this is where you'd do your validation (return message to user if failed) and ultimately send the e-mail.
In the long run I think you'd be better off modifying the flow as I'm currently having a hard time trying to follow it.