3

I am using validate jquery plugin and recaptcha for a contact form and i woudld like to know how can i check if the code in the captcha is correct before the form get submitted if not send an error message because right now validate everything but i inserted a wrong code the form get submitted anyway. Here's my code ty in advance for anyhelp

<script type="text/javascript">
             var RecaptchaOptions = {
                lang : 'en',
                theme : 'custom',
                custom_theme_widget: 'recaptcha_widget'
             };
            </script>

            <form id="contact" method="post" action="#">

                <fieldset>
                    <label for="name_contact">NAME</label>
                    <input type="text" class="input-xlarge" id="name_contact" name="name_contact" value="" placeholder="" minlength="2">

                    <label for="email_contact">EMAIL</label>
                    <input type="email" class="input-xlarge" id="email_contact" name="email_contact" value="" placeholder="">

                    <label for="telephone">CONTACT NUMBER</label>
                    <input type="tel" class="input-xlarge" id="telephone" name="telephone" placeholder="" value="" >

                    <label for="message">MESSAGE</label>
                    <textarea id="message" class="input-xlarge" name="message" placeholder="" rows="5"></textarea>                  

                    <div id="recaptcha_widget" style="display:none">

                        <div id="recaptcha_image"></div>
                        <div class="recaptcha_only_if_incorrect_sol" style="color:red">Incorrect please try again</div>

                        <span class="recaptcha_only_if_image">Enter the words above:</span>
                        <span class="recaptcha_only_if_audio">Enter the numbers you hear:</span>

                        <input type="text" id="recaptcha_response_field" name="recaptcha_response_field" />

                        <div><a href="javascript:Recaptcha.reload()">Get another CAPTCHA</a></div>
                        <div class="recaptcha_only_if_image"><a href="javascript:Recaptcha.switch_type('audio')">Get an audio CAPTCHA</a></div>
                        <div class="recaptcha_only_if_audio"><a href="javascript:Recaptcha.switch_type('image')">Get an image CAPTCHA</a></div>

                        <div><a href="javascript:Recaptcha.showhelp()">Help</a></div>

                    </div>

                    <script type="text/javascript"
                        src="http://www.google.com/recaptcha/api/challenge?k=6Lf8RN4SAAAAAKnllVnDw23UpBIuAIdTRFgN1kmX">
                    </script>

                    <noscript>
                        <iframe src="http://www.google.com/recaptcha/api/noscript?k=6Lf8RN4SAAAAAKnllVnDw23UpBIuAIdTRFgN1kmX" height="300" width="500" frameborder="0"></iframe><br>
                        <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
                        <input type="hidden" name="recaptcha_response_field" value="manual_challenge">
                    </noscript>             

                    <button type="submit" value="" id="" name="send" class="pull-right lightblue btn-primary">SUBMIT</button>
                    </fieldset>
</form>


<script type="text/javascript">
    $(document).ready(function () {

        $("#contact").validate({
            rules: {
                "name_contact": {
                    required: true,
                    minlength: 3
                },
                "email_contact":{
                    required: true
                },
                "message":{
                    required:true
                },
                "recaptcha_response_field":{
                    required:true
                }

            },
            messages: {
                "name_contact": {
                    required: "Please, enter a name"
                },
                "email_contact":{
                    required: "Enter a valid email"
                },
                "message":{
                    required: "Please provide a comment"
                },
                "recaptcha_response_field":{
                    required: "Captcha is required"
                }
            },
            errorPlacement: function(error, element) {
                error.insertBefore(element);
            }
        });

    });
</script>
Sparky
  • 98,165
  • 25
  • 199
  • 285
paoloi
  • 189
  • 2
  • 6
  • 19
  • It's being submitted anyway because of `value="manual_challenge"` within the `name="recaptcha_response_field"` input. Integration with captcha is possible but it's also specific to the captcha system. Please construct a jsFiddle simulation of your form including the captcha portion. – Sparky Mar 13 '13 at 22:10
  • @Sparky here's my file http://jsfiddle.net/9XXHE/ – paoloi Mar 14 '13 at 14:38
  • This requires a complex solution involving both jQuery and your server-side script. My answer below only addresses the jQuery. – Sparky Mar 14 '13 at 16:13

1 Answers1

6

There is no simple solution only using JavaScript or jQuery. Since you have to compare the Re-Captcha code using the API along with your private key, for proper security, you must do this process with some server-side code.

  1. User fills out form correctly except for Re-Captcha code.

  2. If Re-Captcha code is blank, normal required rule in jQuery Validate triggers a "missing Captcha" message. User can try again.

  3. A Re-Captcha code entered (correctly or incorrectly), form is submitted to your server-side code via jQuery ajax within the submitHandler callback function.

  4. Your server-side code, PHP, Perl, whatever, then uses your private API key to verify the entered Re-Captcha code against the Re-Captcha code expected by the API.

  5. If Re-Captcha code is correct, your server-side code continues as normal and returns a "success" text response to your jQuery ajax success callback function.

  6. If Re-Captcha code is incorrect, your server-side code will only return an "error" text response to your jQuery ajax success callback function, and the server-side code will do nothing else.

  7. Within your jQuery ajax success callback function, read the message text returned from the server-side code.

  8. If the returned message indicates a success, then your form was already submitted successfully and you can redirect, clear out the form, do an animation, print a message, do nothing, or whatever, etc.

  9. If the returned message indicates failure, generate a new Re-Captcha code via JavaScript, display an error message, "incorrect Captcha entered", and the user can simply try again.


This is how I did mine... you'll need to do something very much like the following.

Add a submitHandler to your .validate() options and use ajax to control the form submission. It's the only way you can interact with the Captcha and control form submission.

You'll also need to modify your server-side function to test whether the captcha passed or failed, do the appropriate function, and to return the proper ajax message, msg. Without knowing anything about your server-side code, it's impossible to say anything more specific.

(NOTE: any solution that is purely JavaScript/jQuery, without editing your server-side code, is not secure. Captcha can be easily bypassed and your private API key is exposed to the public.)

$(document).ready(function() {

    $("#contact").validate({
        // your other options and rules,
        submitHandler: function (form) {
            $.ajax({
                type: 'POST',
                data: $('form').serialize(),
                url: 'formMail.pl', // <-- whatever your server-side script, mine is a perl form mailer
                success: function (msg) {
                    if (msg.indexOf('captcha') != -1) {
                        Recaptcha.reload(); // reloads a new code
                        $('#recaptcha_response_field').before(msg); // error message
                    } else {
                        // anything else to do upon success, animations, etc.
                        // form was already submitted as per ajax
                    }
                }
            });
            return false; // blocks normal form submit
        }
    });

});

The following is only a PERL example of how I modified my server-side code which was a Form Mailer script. You'll have to adapt your server-side code in some similar fashion.

The subroutine check_captcha is called when the script first runs.

sub check_captcha {     
       my $ua = LWP::UserAgent->new();
       my $result=$ua->post(
           'http://www.google.com/recaptcha/api/verify',
           {
               privatekey => 'xxxxxxxxxxxxx',  # insert your private key here
               remoteip   => $ENV{'REMOTE_ADDR'},
               challenge  => $Form{'recaptcha_challenge_field'},
               response   => $Form{'recaptcha_response_field'}
           }
       );

       if ( $result->is_success && $result->content =~ /^true/) {
               return;  # OK - continue as normal with Form Mailer
       } else {
               # error, Form Mailer will not continue
               &error('captcha_failed'); # failed Captcha code, call error subroutine to print an error message (msg) containing the word "captcha"
       }
}

Remember that this server-side code must return a message that your jQuery picks up within your jQuery ajax success callback as msg above. In my example, if the message contains the word "captcha", that means the code was entered wrong and user must re-enter a new Captcha code.

Sparky
  • 98,165
  • 25
  • 199
  • 285
  • ty @Sparky for your answers, before you post this solution i tried this: I erased the script and the none script after the id="recaptcha_widget" div and use some code from the example captcha file that is in the folder when u download the recaptchalib.php, so now the code it's working when u digit a wrong code, the form gets clean and u have fill the inputs again until u got the right asnwer, I wanted to ask you, if u think this is save? let me post the code in the next comment ty in advance for any answer – paoloi Mar 14 '13 at 19:05
  • is_valid) {echo "You got it!";} else { $error = $resp->error; } } echo recaptcha_get_html($publickey, $error); ?> – paoloi Mar 14 '13 at 19:08
  • @paoloi, Yes... as long as your keys are stored in your PHP code, this is safe. Nobody can access the raw PHP code from the public side. – Sparky Mar 14 '13 at 19:53
  • ty very much @Sparky now i have another question. – paoloi Mar 14 '13 at 20:04
  • i used this example http://www.darksideofthecarton.com/2008/12/15/validating-recaptcha-jquery-ajax/comment-page-2/#comment-23170 and combined it with yours so my submit handler is like this this file is not working but at least give an idea of what im doing http://jsfiddle.net/EaSTa/ the form validation is fine my only problem is that the captcha validation always return the error message, any idea?...and sorry for so much questions, ty again – paoloi Mar 14 '13 at 20:14
  • @paoloi, I see that this line: `submitHandler: function validateCaptcha(){` should be `submitHandler: function(form){`. Otherwise, it's impossible for me to troubleshoot your server-side code... that part is up to you. I know my posted answer is working for me. Also check the value of `html` coming back from server with a `console.log(html);` – Sparky Mar 14 '13 at 20:24
  • i really dont understand your example, i know it is me, dont know exactly how this is done – paoloi Mar 14 '13 at 20:44
  • @paoloi, I don't know how I can make it more clear. What part don't you understand? What about the rest of my comment? The incorrect `function(form)` and my questions about the message coming from your server? – Sparky Mar 14 '13 at 20:59