Quick n’ Dirty Spam Protection

This is the eighth of my Quick N Dirty plugin posts and today the plugin has no hooks at all. The plugin I am explaining today helps to prevent automated spam and is something I have been using on my blog since I started it.
So far, every plugin I have explained has had either an action or a filter to trigger the functionality. The point of each hook is that it lets you intervene in existing functions. In this case however the plugin doesn’t need to do that.
I need the plugin to run some code as soon as it is loaded, which means I simply put the code in plugin file and don’t wrap it in a function, and I need part of it to run at specific points inside the comment form, so I provide a function for that.
To get the plugin working you need to do two things: first install the plugin, second make some changes to you comment form. The following example shows how the function in the plugin should be used:
<?php $time_value = time(); ?> //you only need this once in your template <label for="<?php qnd_useFormField(’url’ , $time_value );?>"><small>Website</small></label> <input type="text" name="<?php qnd_useFormField(‘url’ , $time_value );?>" id="<?php qnd_useFormField(‘url’ , $time_value);?>" value="<?php echo $comment_author_url; ?>" size="22" tabindex="3" />
This code shows a label and the name field. I have used the same function multiple times in the for field of the label, the name and id fields of the textbox.
The first parameter is the old name of the form, in the case url. The second parameter is a variable containing the current time. Notice though that because the function is being used several times the time value needs to be the same each time, so we set the value of the variable once. It will not work properly if you include time() directly in the function call.
You need to do this for all the form fields in the comment form; although the time variable only needs to be set once for the entire form.
So what does it do. Well here is the plugin code, I will explain it below:
<?php /* Plugin Name: Quick n’ Dirty Spam Protection Plugin URI: http://www.wp-fun.co.uk/2008/01/27/quick-n-dirty-spam-protection/ Description: Provides a facility for randomising the names of form fields Author: Andrew Rickmann Version: 0.1 Author URI: http://www.wp-fun.co.uk */ //make sure that a session has started so that we store //information in the session if ( session_id() == "" ){ session_start(); } //limit the replacements so that no other forms are affected. //wp-comments-post is where comments go to be processed if ( $_SERVER[‘PHP_SELF’] == ‘/wp-comments-post.php’ ) { //if we have previously set the session variables //then load them, otherwise just load an array; if ( isset( $_SESSION[‘qnd_formFields’] ) ) { $qnd_form_fields = $_SESSION[‘qnd_formFields’]; } else { $qnd_form_fields = array(); $_SESSION[‘qnd_formFields’] = array(); } //when the session variable is created the name of the //original field is the array key, and the random variable //is the value. foreach($qnd_form_fields as $key => $value){ if ( isset($_POST[$value]) ) { $_POST[$key] = $_POST[$value]; unset($_POST[$value]); } elseif ( isset($_POST[$key]) ) { unset($_POST[$key]); } } } //this function allows us to set the session variable //in the html page. So we replace the name of each form field //with this function function qnd_useFormField( $name , $time ){ //write to the session variable. //create a random number and convert it to a hexidecimal number if ( !isset($_SESSION[‘qnd_formFields’][$name]) || $time != $_SESSION[‘qnd_formFields’][‘time’] ) { $_SESSION[‘qnd_formFields’][$name] = dechex(rand(0,429496729)); $_SESSION[‘qnd_formFields’][‘time’] = $time; } //output the number echo $_SESSION[‘qnd_formFields’][$name]; } ?>
The first thing the plugin does is make sure a session has been started as the plugin saves information in a session variable that is essential for it to work.
When the function is called it adds an entry to the array stored in the session variable, the index is the name of the form field, and it creates a random hexadecimal number for the value of the array entry.
If you load your page and view the source you will find that the form fields now have solely numeric names instead of the previously descriptive names.
The time variable I mentioned before the plugin makes sure that the value changes each time the page is loaded.
When you submit the form the bulk of the code runs automatically. First it checks to make sure that the page the plugin has been loaded on is the the comment handler. This makes sure we don’t mess with any of the form fields for any other forms that you might use on your blog, like the login or contact forms.
Next it retrieves the array from the session that contains the form names. This array is compared to the values that have been submitted in the $_POST variable, i.e. the form fields that have sent data to this page. If a submitted field matches one of the random values stored in the array it replaces this information with the original name of the form field.
If a field with one of the original names has been submitted; for example, if a form field with the name url has been submitted then it will be deleted as we know that value couldn’t have come from our form.
Once the values have been switched WordPress can process the comment in the normal way.
Why does this work?
Randomising the form names means that spambots cannot simply send the default form names to the form handler and expect them to be dealt with. The sessions mean that even if they read the page content and obtain the form names then there is every chance that the form names will have changed again when the bot sends their content.
Note: If you copy the content of this plugin you will need to replace all the quote marks as WordPress replaces them with fancy ones.
Comments
Leave a Reply
I am currently testing a comment link policy which means commenters do not get a link. There is a poll, and open comments for feedback on the comment policy page.

1
Christoph Voigt (http://www.bastelbude.com) commented at 9:01 am, 1st 02 2008:
That’s an interesting approach to preventing spam, however it drastically influences the usability of your site!
Browsers usually rely on the name of forms to fill them with previously typed content. I really don’t want to enter my name, email and website every time I write a comment on a blog that I visit regularly
2
Andrew Rickmann (http://www.arickmann.co.uk) commented at 6:41 pm, 1st 02 2008:
Thanks Christoph, I honestly hadn’t considered it from that angle.
I’m not sure I share you feelings that it is that important, but I guess the solution is that I (or anyone using this) need to offer a remember me option that uses PHP to set those variables behind the scenes.
3
Janis Elsts (http://w-shadow.com/) commented at 7:40 pm, 6th 02 2008:
I just wanted to note that Christoph is wrong here - WP itself fills the fields with previously used values. It uses cookies for this.
4
Andrew Rickmann (http://www.arickmann.co.uk) commented at 7:37 am, 7th 02 2008:
Thanks Janis, that is good to know.
I thought that something like that should happen but as I have never commented on my blog without being logged in I wasn’t in a position to test that.
5
Malliobiana (http://www.cathetel.com) commented at 5:53 pm, 15th 06 2008:
I like the Comment Link policy which means that the commenters do not get a link, the only problem being that it might actually drive good commenters away, as normally a good comment is in essence rewarded with a link. But it sure cuts down on the worthless reams of time wasting spam. And that’s the good point.