Welcome to CrankyGoblin.Com Sign in | Join | Help

Public Class GeoffAppleby

Inherits Microsoft.VisualBasic.MVP : Implements IBrainFart
Gaptcha Source

Version 1.0 of the Gaptcha Control is now ready for public consumption (should anyone want it :) Download it here.

Sadly, to add Gaptcha to your site it's not just a simple matter of just dropping an assembly in your bin folder - there's a few different patches to be made. The purpose of this article is to guide you through patching it into your community server source. If you're not using Community Server but want to use the Gaptcha control, feel free to implement it yourself, but I can't help you I'm sorry. Feel free to talk to me about it though (and please, if you do implement your own, let me know - it would to be cool to know if it spreads :) Also, I've written this using .Net Framework 2.0 features - if you are running your community server against the 1.1 Framework, this won't work. I'll look at updating it in the future if people ask me too.

There's a few different things that need to be covered for this guide.

  1. Making the required changes to the database.
  2. Adding custom objects.
  3. Patching the DataProviders.
  4. Adding extra configuration options.
  5. Adding the management screens to the Control Panel.
  6. A quick walk through on how to use the management screens.
  7. Adding the core code for the Gaptcha control.
  8. Updating the blog skins to have the Gaptcha control available.
  9. Enabling the Gaptcha control on a blog.

Just about all the files used in this guide are provided in a download, mirroring the file paths of the Community Server SDK (2.1). Don't just extract the zip file over the top of your current source base - you may have made other changes to the same files already (or I might have some other custom changes) so everything will just go screwy. Please, follow the walk through carefully until you're familiar with what needs to be done.

Also remember that this is version 1.0. I'm happy enough with how this version works, but there's still some changes I want to make, and extra features to add (especially in the management screens/options). but I have to draw the line somewhere, and this is it. It works, and quite nicely, but I'm sure that version 1.1 will come out some day with a few enhancements :)

Making the Required Changes to the Database

This step is pretty easy. You'll find a SQL script in the zip archive at Gaptcha Source\SqlScripts\cs_2.1_CreateGaptcha.sql. Run this file against your database, and it will be Gaptcha ready. It adds a new table (cs_weblog_gatpcha) and a few different procs for adding, editing and listing.

Adding Custom Objects

I made two custom classes to hold the 'GaptchaImage' object, which I put in the Components area of CommunityServer.Blogs. Copy them from Gaptcha Source\source\Blogs\Components to your code base. There's two files - GaptchaImageList.cs and GaptchaImage.cs. Having copied them, include them in the CommunityServerBlogs20 project. You should be able to compile your source at this stage - nothing has really changed yet, but you can do it if you want to prove that everything is correct so far :)

Patching the DataProviders

To patch the data providers, first you need to do the base class, then update the SQL implementation of it. You'll find the base class at Gaptcha Source\source\Blogs\Providers\WeblogDataProvider.cs. Open this file and copy everything in the GAPTCHA region (lines 83 to 93) into a suitable section in CommunityServerBlogs20\Providers\WeblogDataProvider.cs.

The Sql data provider also needs to be patched. You can find the needed code in the GAPTCHA region in Gaptcha Source\source\Data Providers\SqlDataProvider\WeblogSqlDataProvider.cs. The region starts at line 172 and finishes on line 340. Paste the code into a suitable section in SqlDataProvider20\WeblogSqlDataProvider.cs. Again, you should be able to compile your source at this stage - the data providers have been modified, but the code is never called, but if it compiles you must be doing the right thing, right? :)

Adding Extra Configuration Options

As I wrote Gaptcha I decided that it needed some configuration options. Where else do these get stored than in communityserver.config? :) There's a couple of options to add to this file, and then the config handlers need to be updated so that they can read the values out.

You can find a sample config in Gaptcha Source\source\Web\communityserver.config. It only contains the Weblog section, and has 4 new config options for you to set.

<Weblog

    gaptchaImageCount = "9"

    gaptchaImageSelectionCount ="3"

    gaptchaTimeoutEnabled ="true"

    gaptchTimeoutMinutes ="10"

  • gaptchaImageCount - this is the number of random images to show on the comment form.
  • gaptchaImageSelectionCount - the number of images selected from the gaptchaImageCount images that must be clicked on when submitting a comment.
  • gaptchaTimeoutEnabled - set to 'true' to enable timeouts, or 'false' to turn it off. If true, then the selection of images for a given page can only be submitted within particular time period.
  • gaptchaTimeoutMinutes - the number of minutes that must pass for a timeout to occur. Only required if gaptchaTimeoutEnabled = true.

Paste them into the Weblog node in your own communityserver.config file in the CommunityServerWeb20 project, and then update the values as you see appropriate.

Note: I plan in a later version to make these values configurable on a per-blog basis, but for now it's global.

To access these values from code, it's a simple matter of updating the WeblogConfiguration class. You can find the needed code in Gaptcha Source\source\Blogs\Components\WeblogConfiguration.cs, and you need to update CommunityServerBlogs20\Components\WeblogConfiguration.cs.

In the Initialize() method, add the code that parses the values out of the xml (in the Gaptcha source file this code is at lines 62 - 78. Then add the exposed properties to wrap them (which you can find in the GAPTCHA region, lines 170 - 200.

Again at this stage your code should compile successfully. Again, you can't do anything with Gaptcha, but it's nice to see.

Adding the management screens to the Control Panel

The management screens were a lot of fun, especially figuring out how to use Telligent's cool modal window thingy (it comes up when you edit Tags, etc). There's four things that need to be done to get the management screens up and going.

  1. Add the ManageGaptcha page and it's popups. Most of the management of Gaptcha is is done on new pages within the control panel. Copy these files from Gaptcha Source\source\Web\ControlPanel\Blogs into CommunityServerWeb20\ControlPanel\Blogs, and include them in the project.
    • GaptchaAdd.aspx
    • GaptchaAdd.aspx.cs
    • GaptchaForm.aspx
    • GaptchaForm.aspx.cs
    • ManageGaptcha.aspx
    • ManageGaptcha.aspx.cs
  2. Modify CommunityServerWeb20\ControlPanel\Blogs\NavBar.config to include a reference to ManageGaptcha.aspx. I've included mine as a reference. You must use the exact same XML as what I have, but you can position it within the nav bar anywhere you like.

    <Tab resourcename="CP_Blog_NavBar_GaptchaManagement" href="~/ControlPanel/Blogs/ManageGaptcha.aspx" name="GaptchaManagement" />

  3. Next we need to set an ExtendedAttribute on a WebLog object to allow us to store if gaptcha is enabled for a specific blog. In Gaptcha Source\source\Blogs\Components\WebLog.cs you will find a region down the bottom labelled 'GAPTCHA' which contains the extra functions to be added. Patch them in to your copy of WebLog.cs in CommunityServerBlogs20/Components.
  4. Update your default post settings to allow Gaptcha to be enabled on a per-blog basis. In Gaptcha Source\source\Web\ControlPanel\Blogs I've included my DefaultPostSettings.aspx and DefaultPostSettings.aspx.cs files, which map to the same files in CommunityServerWeb20/ControlPanel/Blogs/ files.
    • DefaultPostSettings.aspx: I added an extra table row on row 2, giving radio buttons to dis/enable gaptcha on a specific blog, as well as providing an extra link to the ManageGaptcha.aspx page.
    • DefaultPostSettings.aspx.cs: This one's pretty simple. I added the member declaration for the yes/no control. I then added setting it's value in page load, and added saving it's value in the SaveButton_Click event.
  5. I've tried to be a good boy here and put all display strings in the assorted resource files that Community Server uses - so you need to merge in the new resource strings too. At Gaptcha Source\source\Web\Languages\en-US there's two files - ControlPanelResources.xml and Resources.xml. They contain JUST the new resources - copy the contents of each one into the equivalent xml file in CommunityServerWeb20/Languages/en-US.

Again, having got this far, everything should compile again. In fact, the site should be working again, and you can go into your control panel and play with the Gaptcha management screen. 

A Quick Walk Through on How to Use the Management Screens

I've based the management screen heavily on both the 'Review Comments' and 'Tags / Keywords' pages in ControlPanel, so you should find it pretty easy to use.


(click for a larger version)

Here's a shot of how it looks. You can select multiple entries and then enable, disable, or delete them all at once. You can edit or delete individual entries, and you can add a new image up the top.

The Add screen is just a matter of entering an image to upload, and setting a description.

The Edit screen is even easier.

If you disable an image, it's still present in the management screens and in the database, but it will never appear on a comment form.

Adding the Core Code for the Gaptcha Control

Now it's time to add the actual control itself. But first we need to create a new control that I use within the Gaptcha control :)

In Gaptcha Source\source\Controls\Utility you will find ResourceLabel.cs. It's a Community Server control that works like a label control, but it reads it's text from the Resources.xml file. I needed to extend it, so if you open this file up you'll see a second class has been added. This class, which I called the FormattableResourceLabel, inherits from the original ResourceLabel. It allows for resource strings to contain a {0} wildcard, and will call String.Format on the resource text, passing as an argument the newly added Argument property. Add this new class to the bottom of your own CommunityServerControls20/Utility/ResourceLabel.cs (or in a new file, it's up to you. But make sure you keep the correct namespace).

Again, everything should compile fine at this stage.

Now we can add the Gaptcha control. Copy Gaptcha Source\source\Blogs\Controls\CommentGaptcha.cs to CommunityServerBlogs20\Controls, and include it in the CommunityServerBlogs20 project. Once you've done that, you'll see that I left my encryption keys in there for encrypting the hidden form data. Feel free to change them if you want.

Next we need to get the CommentForm control to know that it might be hosting the GaptchaControl, and to validate against it if required. I've provided my copy of the file at Gaptcha Source\source\Blogs\Controls\CommentForm.cs. If you haven't modified your version of the control, it might just be easiest to overwrite the entire file :)

Basically, all I've done is is:

  • Declare a private member to point at a CommentGaptcha object.
  • Try to assign it using the FindControl() method. (AttachChildControls).
  • If it was found, databind against it. (AttachChildControls).
  • If it was found, call it's Validate() method. (btnSubmit_Click).

Actually, that doesn't sound too hard :)

Updating the blog skins to have the Gaptcha control available

Each blog skin needs two things: The comment form skin needs to declare a gaptcha control on itself; and a skin file for the gatpcha control itself. Luckily, the skin engine for CS uses inheritance, so if a skin doesn't have a particular skin file, it uses the skin that it inherited from it.

As a result, I've only written one skin file for the Gaptcha control - one for the default skin. You can get it from Gaptcha Source\source\Web\Themes\Blogs\default\Skins\Skin-CommentGaptcha.ascx, and you just need to copy it to CommunityServerWeb20\Themes\Blogs\default\Skins. There's one thing in there you have to edit - I put in a link to a page on my own blog with plain pictures of my family so that people can learn who everyone is. You might want remove or edit that part :)

The comment form now needs to load the control. This is where you need to update every skin you have that provides a skin file for the comment form - I'll show you how it's done for the default skin, and you can do the rest yourself. I've put in the zip file my comment form skin file for the default theme, at Gaptcha Source\source\Web\Themes\Blogs\default\Skins\Skin-CommentForm.ascx. I made two changes to this file from the original - a tag prefix registration near the top:

<%@ Register TagPrefix="CSB" Namespace="CommunityServer.Blogs.Controls" Assembly="CommunityServer.Blogs" %>

and including the control itself, which I did just before the submit button.

    <dt><asp:CheckBox id="chkRemember" runat="server" Text="Remember Me?"></asp:CheckBox></dt>

    <dt><CSB:CommentGaptcha id="gaptcha" runat="server" /></dt>

    <dt><asp:LinkButton CssClass="CommonTextButton" id="btnSubmit" runat="server" Text="Submit"></asp:LinkButton></dt>

And that's it!

Enabling the Gaptcha Control on a Blog

To enable it fully, you need to make sure that that blog's skin will include the control, and you need to flick the switch.

To flick the switch, go into the Control Panel and select your default post settings. It's now just a matter of selecting 'Yes' for 'Require GAPTCHA validation for comments', and saving the change. Don't forget to upload some images first :)

So that's it.

Please, if you find any problems, have any suggestions, or even simply just install it on your blog, I'd love to hear about it.

While I'm at it, here's a list of things you don't need to suggest (because I've already thought of them and plan on putting them in the next version):

  • Allowing the numbers (gaptchaImageCount, gaptchaSelectionCount and gaptchaTimeoutMinutes) to be customised on a per-blog basis.
  • Allowing blog owners to change the image for a gaptcha entry - currently you have to delete it and create a new one.
  • I'd like to see how much of all this can live in it's own assembly, so there's less patching of the source required.
  • Changing it so that a hard coded encryption key is not required, but instead generates the keys randomly at Application_Start().
  • Actually deleting the uploaded image when you delete an entry.
  • Randomly creating filenames for uploaded images.

And here's my list of issues/precautions to take:

  • The name of the image uploaded is saved with the same name as what you uploaded it as. If all 30 of your gaptcha images are called 'Image5.jpg', then each one will over-write the one before it.
  • The name of the image uploaded is saved with the same name as what you uploaded it as. So if you have really descriptive image file names, and  spam bot gets through because yo had image called 'MeAtTheBeach.jpg' had a description of 'Me At The Beach', that's your own fault (see the last note in the list of ideas I've had for the next version).
  • I think I coded for it, but I can't remember what will happen if you only have 3 images uploaded, and it tries to show 9 :)

Again, any feedback is highly appreciated :)

Posted: Tuesday, 24 October 2006 3:00 PM by Geoff Appleby

Comments

Public Class GeoffAppleby said:

Update: The source is now live ! Tonight I made a couple of little mods to my Gaptcha control. First,

# October 25, 2006 5:07 PM

Public Class GeoffAppleby said:

Update: The source is not live ! Well, I was up until 1am this morning getting it polished enough, and

# October 25, 2006 5:07 PM

Public Class GeoffAppleby said:

Update2: The source is now live ! Update: It&#39;s now live! Thanks for the support everyone :) It&#39;s

# October 25, 2006 5:09 PM

Public Class GeoffAppleby said:

Update: The source is now live ! I never thought I&#39;d do it, but the day has arrived. I&#39;m starting

# October 25, 2006 5:09 PM

Public Class GeoffAppleby said:

Update: The source is now live ! I&#39;ve been working on getting the source for Gaptcha all cleaned

# October 25, 2006 5:10 PM

External News Feed said:

news of the day a grab bag for what's happening in Community Server If you dare to explore the mind behind

# October 30, 2006 2:17 PM

Daily News Faq List said:

If you dare to explore the mind behind GAPTCHA, Geoff Appleby has provided his GAPTCHA source code with

# November 22, 2006 8:04 AM

Community Server Bits said:

If you dare to explore the mind behind GAPTCHA, Geoff Appleby has provided his GAPTCHA source code with

# March 12, 2007 5:30 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

To submit your comment, click on these pictures:
  • Shocked Geoff
  • Geoff's pretty blue eyes
  • Searching Geoff
Gaptcha Image - No Peeking! Gaptcha Image - No Peeking! Gaptcha Image - No Peeking!
Gaptcha Image - No Peeking! Gaptcha Image - No Peeking! Gaptcha Image - No Peeking!
Gaptcha Image - No Peeking! Gaptcha Image - No Peeking! Gaptcha Image - No Peeking!
Can't recognise the people in these pictures? Look here for a quick introduction.
There's a time limit for you to get your comment submitted before this set of pictures expires. If you think it's been longer than 10 minutes, get some new pictures first (you won't lose what you've typed so far).
Get some new pictures 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS