Blogless: Blog of Design Less Better.

Making the reCAPTCHA Wordpress Plugin Validate

If you are like us, you want to harness the awesome power of reCAPTCHA for your Wordpress blog and you also want valid XHTML. Before now, this was impossible. DLB is pleased to offer you a fix, and continue doing our bit to make the web a more standardized place.

Background

reCAPTCHA is a free CAPTCHA service that helps to digitize books.

A CAPTCHA is a program that can tell whether its user is a human or a computer, by asking the user to copy some distorted text. You’ve probably seen them, either here, or elsewhere on the web. If not, just click here for an example.

Reading Spidey
The Internet Archive is going to help Spidey enter "the digital age".

reCAPTCHA gets these words from books that the Internet Archive is digitizing. Digitizing books is done by photographically scanning the book’s pages, and then transforming these scans into text using “Optical Character Recognition” (OCR).

All this together means that when you leave a comment, in addition to contributing to the discussion, you are both proving you are a person, not a spambot, and helping humanity’s effort to archive it’s knowledge digitally.

The Problem

Which is all milk and honey, but there’s a problem. As good citizens of the web, and as Wordpress users, BlogLESS utilizes reCAPTCHA’s handy Wordpress Plugin. But, as good citizens, BlogLESS is further committed to web standards. This means that all our HTML and CSS needs to be valid. Unfortunately, the Wordpress reCAPTCHA plugin doesn’t validate XHTML out of the box. (As it turns out, this is not its fault. It actually can’t validate out of the box, which we’ll see.)

The good news is, the fix is easy, once you understand the problem. You don’t need to be a pro to make your Wordpress comments template valid again.

The Fix

First, you’ll need to find the php files that write the reCAPTCHA to your comments template. They are two, although the file names changed between versions. I’ve checked against the lastest (v2.91), and the oldest version I could find (v2.5). If your version is somewhere in the middle of the two, you’ll have to extrapolate a little, but it shouldn’t be hard.

Anyhow, both versions have a file called recaptchalib.php. Version 2.5 has a second file called recaptcha.php, which changed to wp-recaptcha.php by 2.91. In any case, they should both be found in a directory that looks something like this:

[blog root]/wp-content/plugins/recaptcha-wordpress-[version]

Error the first

By 2.6, reCAPTCHA fixed this first error, so if you’re up-to-date, you can skip this step and move on to Error the second below. However, if you’re using 2.5, the fix is very easy. Open recaptchalib.php, and locate lines 126 to 130. These lines contain a complete <noscript> block. Find it and replace it with the following:

	<noscript>
  		<iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" 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>';

Error the second

That one was just sloppy, and again, was fixed early in the plugin’s development. Unfortunately, the second validation failure is quite a bit more insidious. It takes place in the main plugin file ([wp-]recaptcha.php). In 2.5, find line 57. In 2.91 it’s line 431. In any case it looks like this:

	<style type='text/css'>#submit {display:none;}</style>

The w3c tells us that this error is because "The element named above was found in a context where it is not allowed. This could mean that you have incorrectly nested elements — such as a ’style’ element in the ‘body’ section instead of inside ‘head’…" Jackpot.

As it turns out, this puts us in a bit of a jam. Why? First, we’re in a noscript block, so we can’t apply this definition with Javascript (the most obvious choice). Second, the purpose of this definition is to hide a submit button that occurs in our Wordpress comments template and replace it with the one that we create on the following line (59,432) of our plugin file. This means we can’t use an plugin-scope PHP conditional.

So, the somewhat counter-intuitive way to handle this — but the only valid way you’re going to get — is to make two alterations. First, comment out the line that’s causing the trouble:

	<!--<style type='text/css'>#submit {display:none;}</style>-->

Now, open your comments template, usually:

[blog root]/wp-content/themes/[theme name]/comments.php

and find the submit button (any input with id="submit"). Now what we’re going to do is actually only write the submit button for browsers that support javascript. Instead of your defacto submit button, use something like this:

	<script type="text/javascript">
		//<![CDATA[
		/* Cf. http://www.designlessbetter.com/blogless/posts/making-recaptcha-validate */
		document.write('<input name="submit" type="submit" id="submit" tabindex="5" value="Post this Comment" />');
		//]]>
	</script>

Awesome!

These icons link to social bookmarking sites where readers can share and discover new web pages.
PaulJul 21, 2008
 

Comments on this post

1.

Paul,

Thanks for your comment on my blog post about this same issue.

I’m interested in knowing more about how your Javascript addition to comments.php solves the problem. It seems to me that since most browsers have Javascript enabled, this solution outputs multiple ’submit’ buttons in most cases.

I’m glad others are trying to tackle this issue also.

Tom Distler at 9:17am on Tue, Jul 22nd.

2.

Tom,

You’ll notice that I’m not suggesting that you add a submit button to your comments.php. I’m suggesting that you replace the normal one with one that is output by Javascript. If you think about it, this means that the submit button will now display only for those users with Javascript enabled.

The net effect of this is that users with Javascript enabled get one submit button, and users without get zero. This is identical to the effect created by writing a submit button for all browsers and then setting the ‘display’ style to ‘none’ for browsers with Javascript disabled.

You can see for yourself by disabling Javascript in your browser.

Hope this clears things up,
Paul

Paul at 9:59am on Tue, Jul 22nd.

3.

Post updated. I still have some tweaking to do to prevent a rogue input field from showing up w/ scripts disabled, but that’s a lower priority. Thanks again!

Tom Distler at 1:08pm on Tue, Jul 22nd.

4.

Awesome, thanks for the information man, I really appreciate it. I will link to this page from the plugin description page. Hopefully the reCAPTCHA developers eventually fix this problem. Thanks for the solution in the meantime though.

Blaenk at 4:07pm on Tue, Jul 22nd.

5.

@Blaenk - Glad to be of service, and thanks for your hard work maintaining this useful plugin. Thanks for the link also.

@Tom - Thanks for the link and good luck with your rogue field.

Paul at 6:51am on Wed, Jul 23rd.

6.

Hi - Many thanks for addressing the very issue that I came across (style tag in wrong place). Awesome blog design btw.

Narada at 6:46am on Sun, Jan 4th.

7.

Thanks, Narada. Glad to be of service.

Paul at 10:03am on Sun, Jan 4th.

8.

Great article. I was searching for some information on the recaptcha plugin for wordpress and found this. There is also another simple article that describes how to include five most used plugins at

http://www.madanrevoor.com/web-designing/wordpress-plugins-five-most-useful-wordpress-plugins-for-your-website

Ali at 10:03am on Tue, Feb 24th.

9.

Except you’re cheating with XHTML transitional! ;) In strict mode (the default for the latest Wordpress I believe?) the iframe element is not allowed. I replaced the iframe with an object instead. The iframe is retained for IE, using a conditional comment. Apparently IE won’t load a URI from another domain into an object by default.

This approach would present problems for some edge case browsers that can support neither JavaScript nor the object element.

<!--[if IE]-->

As for the submit buttons, I can’t see the need for hiding the one button and then adding another one. Both are inputs of type “submit” and both have the same name/value combination. Can’t that whole noscript block be taken out? Or am I missing something obvious? Testing didn’t seem to reveal any problems.

Michael Newton at 7:46pm on Mon, Apr 13th.

10.

Hmmm, the value of a comment preview is displayed above.

Michael Newton at 7:48pm on Mon, Apr 13th.

11.

Hi Michael.

Glad to hear you’ve found a fix that validates XHTML strict. The Recaptcha plugin comes by default using an iframe, which works for those of us who validate against the Transitional DTD, so — frankly — the need to replace it it hadn’t occurred to me.

On the Javascript tip: To understand what’s going on, you have to view your reCAPTCHA on a browser with Javascript disabled. The way the plugin works when js is disabled is that it hides the default Wordpress comment submit button, replacing it with its own. If it didn’t do this, you’d be able to just submit your comment without entering a CAPTCHA, thus defeating the purpose of the whole thing. As it stands, you have to enter the CAPTCHA, and then it gives you a confirmation code, which you have to paste into a form. The submit button for the form has to authenticate that code before it submits the comment, which the default Wordpress button doesn’t do. (This all gets handled gracefully by the Recaptcha [Javascript] API when js is available.)

The way it does this by default is to hide the Wordpress submit button with CSS. This isn’t valid because the style definition takes place in the body. So what I do instead is remove the CSS script block from the noscript block in the body (note: with this block in place, the net effect is that the submit button is hidden in non-js browsers, making it visible only in js-enabled browsers), and replace it with a little javascript in the comments template that writes the submit button (note: same net effect).

PS. Fixed the code definition in comments. Comment previews would be nice, someday, time permitting. :)

Paul at 8:39am on Tue, Apr 14th.

Trackbacks

  1. BlogLESS : Less is Better Design Edition: Animating the HAL 9000 on Fri, Aug 8th
  2. Bookmarks about Plugin on Wed, Sep 10th

Post a comment

Name
Email
Url
Comment
  Please feel free to use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>
Validate
Close this
E-mail It