[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 399
  • Last Modified:

php-generated message

I'm testing a very simple captcha on my website's contact form, because the form is being abused by spambots.  I'm at the beginning of the learning curve with php, and plan to refine this captcha in the future.  Meanwhile, there is a specific issue I'd like to resolve...   The php code generates messages which prompt the visitor to complete required form fields, and all but one of these messages appear as popups, without opening a new browser window.   However, a message informing the visitor of a captcha error opens a new browser window.  When that happens, the visitor needs to use the back button, and repopulate the contact form.  Some browsers preserve the form field data, but not Internet Explorer.  I don't know why that particular message behaves this way, but I'd prefer the message appear as a popup, like the other messages.  For example, if the Email field doesn't contain a valid Email address, there is a message prompting the visitor to correct it.  Please advise how to adjust my code so that a captcha error can be corrected without leaving the contact form page.  The contact page is at www.mauitradewinds.com/contact.htm  and the php code snippet is attached.


<?php 
$errors = '';
$myemail = 'stay@mauitradewinds.com';//<-----Put Your email address here.
if(empty($_POST['firstname'])  || 
   empty($_POST['lastname'])  ||
   empty($_POST['email']) || 
   empty($_POST['captcha']) || 
   empty($_POST['message']))
{
    $errors .= "\n Error: At a minimum, we need your name, Email address and message in order to transmit your form.";
}
else
{
    $firstname = array_key_exists('firstname',$_POST) ? $_POST['firstname']:''; 
    $lastname = array_key_exists('lastname',$_POST) ? $_POST['lastname']:''; 
    $email_address = array_key_exists('email',$_POST) ? $_POST['email']:''; 
    $message = array_key_exists('message',$_POST) ? $_POST['message']:''; 
    $captcha = array_key_exists('captcha',$_POST) ? $_POST['captcha'] : FALSE;
    if (!preg_match(
    '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/i', 
    $email_address))
    {
        $errors .= "\n Error: Invalid email address";
    }
     if (!preg_match(
     "/Maui/i",
     $captcha))
    {
        $errors .= "\n Error: Please check your spelling and try again";
    }
}

if( empty($errors))
{
	$to = $myemail; 
	$email_subject = "Contact form";
	$email_body = "You have received a contact form from Site-1. ".
	" Here are the details:\n First Name: $firstname \n Last Name: $lastname \n Email: $email_address \n Message: \n $message"; 
	
	$headers = "From: $myemail\n"; 
	$headers .= "Reply-To: $email_address";
	
	mail($to,$email_subject,$email_body,$headers);
	//redirect to the 'thank you' page
	header('Location: thankyou.htm');
	exit;//You should always "exit" immediately after a redirection request
} 
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html>
<head>
	<title>Contact form handler</title>
</head>

<body>
<!-- This page is displayed only if there is some error -->
<?php
echo nl2br($errors);
?>


</body>
</html>

Open in new window

0
ddantes
Asked:
ddantes
  • 4
  • 3
1 Solution
 
Ray PaseurCommented:
Please advise how to adjust my code so that a captcha error can be corrected without leaving the contact form page.
Sorry, it can't be done.  CAPTCHA does not work that way.

The whole point of CAPTCHA is to give us a server-side test that can be run after the form has been submitted.  It is only run on the server (there is no JavaScript involved).  It is tested after the form has been submitted and no other changes can be made to the data.  CATPCHA, if successful, verifies that a human entered the information in the form.  And the CAPTCHA, if it fails, fails after the form has been submitted and the original form script is no longer running.

Think about it for a moment... If the client could say, "the CAPTCHA is OK" what would be the point of testing the CAPTCHA at all?  The CAPTCHA is to test the client's input for "humanness."  So it wouldn't make any sense to rely on the client to tell the server it was a human -- that would invite automated form submissions from a 'bot that lied about being a human!

You can make the whole CAPTCHA process suck less if you follow this general design

1. In the form script, try to use elements in $_SESSION to populate the HTML form input controls.  If they are there, use them.  If they are not there, use blanks
2. In the action script (after data validation and sanitization) copy the data from $_POST into $_SESSION.
3. If the CAPTCHA fails, tell the client and give a link back to the form script.

An alternative to using the session is to use a single script file for both the form and the action script (example below).

By doing that you can preserve the posted data so the client does not have to retype all of the information in the form.

Here is the design pattern that shows how to preserve the good information, show error messages about the bad information.  It does not have a CAPTCHA, but I think you can get the idea.

<?php // demo/form_highlight_errors.php
error_reporting(E_ALL);

/**
 * DEMONSTRATE HOW TO HIGHLIGHT ERRORS IN FORM INPUT, AND REMEMBER VALID INPUTS
 * CLIENT IS ASKED TO PUT IN A VALUE
 * IF THE VALUE FAILS OUR TEST WE SHOW AN ERROR MESSAGE
 * WE PUT A MARKER NEXT TO THE INPUT CONTROL ON THE FORM
 * WE TURN THE FORM BORDER RED
 * SEE http://www.w3schools.com/CSS/pr_class_visibility.asp
 */


// THESE STYLE ELEMENTS ARE SET FOR THE SCRIPT INITIALIZATION
$error_abc = $error_xyz = $error_any = 'hidden';
$boxer_abc = $boxer_xyz              = 'black';


// CAPTURE AND NORMALIZE THE POST VARIABLES - ADD YOUR OWN SANITY CHECKS HERE
$abc = (isset($_POST["abc"])) ? trim(strtoupper($_POST["abc"])) : NULL;
$xyz = (isset($_POST["xyz"])) ? trim(strtoupper($_POST["xyz"])) : NULL;


// IF ANYTHING WAS POSTED, VALIDATE IT
if (!empty($_POST))
{
    // VALIDATE THE 'abc' FIELD
    if ($abc != 'ABC')
    {
        // VALIDATION FAILED
        $error_abc = $error_any = 'visible';
        $boxer_abc = 'red';

        // BECAUSE THIS FAILED VALIDATION, REMOVE IT FROM THE FORM
        $abc       = NULL;
    }

    // VALIDATE THE 'xyz' FIELD
    if ($xyz != 'XYZ')
    {
        // VALIDATION FAILED
        $error_xyz = $error_any = 'visible';
        $boxer_xyz = 'red';

        // BECAUSE THIS FAILED VALIDATION, REMOVE IT FROM THE FORM
        $xyz       = NULL;
    }

    // DO WE HAVE INPUT FREE FROM ANY ERRORS?
    if ($error_any != 'visible')
    {
        echo "CONGRATULATIONS";
        die();
    }

    // OTHERWISE... OOPS - WE HAVE ERRORS AND MUST SHOW THE FORM AGAIN
}

// IF NOTHING WAS POSTED, OR IF THERE ARE ERRORS, WE NEED NEW CLIENT INPUT
$form = <<<ENDFORM
<style type="text/css" media="all">
.error_any { visibility:$error_any; }
.error_abc { visibility:$error_abc; }
.error_xyz { visibility:$error_xyz; }
</style>
<pre>
<form method="post">
<span class="error_any">PLEASE CORRECT THE FOLLOWING ERRORS</span>
<span class="error_abc">YOU MUST ENTER 'abc' IN THIS FIELD</span>
PLEASE ENTER "ABC" HERE: <input style="border-color:$boxer_abc;" name="abc" value="$abc" />
<span class="error_xyz">YOU MUST ENTER 'xyz' IN THIS FIELD</span>
PLEASE ENTER "XYZ" HERE: <input style="border-color:$boxer_xyz;" name="xyz" value="$xyz" />
<input type="submit" />
</form>
ENDFORM;

// WRITE THE FORM WITH THE APPROPRIATE CSS STYLES ON THE ERROR MESSAGE FIELDS
echo $form;

Open in new window

0
 
ddantesAuthor Commented:
Thank you.  It will take me a while to explore your recommendations, and I appreciate the sample code.   However, when you say "it can't be done", perhaps I failed to articulate my question clearly.  When I visit a page with a captcha, and I mistakenly enter an erroneous character, there is a popup on that very page, telling me I failed the test.  I can correct my mistake without reloading the page and starting the entire process over.  I'm asking how to create that behavior for a captcha error on my contact form, instead of navigating away from the form to display an error on a new page.   If you try the form, and enter an invalid Email address, you will see a popup asking you to correct that.  I'd like that to happen when there is a captcha error.

I believe the key to this is in the contact.htm  html, toward the bottom of the page, in the javascript relating to form validation.  The code "frmvalidator.addValidation("captcha","captcha","Please check your spelling and try again");"  is not having any effect.
0
 
Ray PaseurCommented:
I can correct my mistake without reloading the page and starting the entire process over.
I think I see where that is coming from.  This is not going to be a short explanation.  First you need to understand the nature of client/server protocols, especially as they impinge on browser activity and the "Ajax" look of web 2.0 applications.  It does not appear to you that you're reloading a web page, but there is still an HTTP request occurring in the background, and its response is reloading a DIV on the page.  It's just not reloading the entire page.  In other words, the call to the server to validate the CAPTCHA is being masked.  But it is still there, and after the form is submitted, the server must still validate the data to ensure that the data has not been tampered with between the initial CAPTCHA verification and the submission of live data.

I'd like to help further, but this is not really a question with an answer, so much as a requirement for web application development.  To achieve this, you would need to understand these technologies fairly thoroughly: HTML(5), CSS(3), JavaScript and jQuery, HTTP, PHP.  It's not rocket science but it is a couple of semesters of college-level engineering studies.  This article may help clarify what is going on at the HTTP level.
http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Jquery/A_10712-The-Hello-World-Exercise-with-jQuery-and-PHP.html
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
ddantesAuthor Commented:
That was very helpful.  Before closing the question, may I ask your opinion about adding this code to the javascript validation section of the html page?

frmvalidator.addValidation("captcha","regexp=Maui","Please check your spelling and try again");

Of course, that is providing the answer to the captcha.  However, should I be concerned that a spam bot will be able to harvest that from the html and insert it in the captcha field?
0
 
Ray PaseurCommented:
I don't really know for sure.  I'm not very good with JavaScript and it would be a research project for me.  My general sense is that you can hide and pass information in the PHP session and this information will be invisible to 'bots.  So I would lean in that direction rather than putting the answer into the HTML document in clear text.  There are many levels of CAPTCHA in the article and none of them would put the answer into the HTML document.
0
 
ddantesAuthor Commented:
Thank you for all your input!
0
 
Ray PaseurCommented:
Thanks for using E-E and best of luck with your project, ~Ray
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

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