• Home
  • Consultancy
  • Contact
  • Loosely coupled Elgg extensions (Captcha example)

    June 15th, 2009 by Marcus Povey

    A new CAPTCHA approachOne thing we try and do when working on a new Elgg feature is – where we can – couple things together as loosely as possible and provide hooks for third party developers to extend Elgg and fill in any blanks.

    A good example of where this has been done is the newly introduced Captcha functionality available in the latest nightly testing builds of Elgg.

    The Captcha functionality is provided by a module which extends a view called “input/captcha“. This view is blank by default but is used in several places such as user registration and the lost password form.

    This means two things; firstly that if a Captcha module isn’t installed or enabled then forms behave normally, and secondly it becomes a trivial matter for third party modules to provide their own Captcha functionality.

    This same mechanism is how the URL shortener module works by the way.

    Next, the Captcha module extends a number of actions to require a correctly validated Captcha code. This list itself is the product of a plugin hook which returns an array of actions which require Captcha validation:

    $actions = array();
    $actions = trigger_plugin_hook('actionlist', 'captcha', null, $actions);

    ...

    function captcha_actionlist_hook($hook, $entity_type, $returnvalue, $params)
    {
    if (!is_array($returnvalue))
    $returnvalue = array();

    $returnvalue[] = 'register';
    $returnvalue[] = 'user/requestnewpassword';

    return $returnvalue;
    }

    The reason why the list of actions is provided this way is twofold, firstly it lets modules use Captcha functionality in their own code through a generic interface, and secondly it is harder to spoof than looking for some marker in the form code.

    The Captcha itself injects a server generated token into the form, which together with the user’s response to the characters generated in an image are used to validate that the user is indeed human.

    As we can see, Elgg asks to be provided with a Captcha if one is available by including a specific view, but is agnostic as to where (or indeed if) this functionality is supplied.

    By using the techniques available to an Elgg programmer I was able to loosely couple the Captcha system to Elgg in such a way that a third party can easily use the same techniques to provide a more advanced module.

    Happy coding!

    Image “A new Captcha approach” by XKCD

    Extending actions in Elgg

    May 8th, 2009 by Marcus Povey

    Those eagle-eyed developers who have been tracking the Elgg core SVN may have noticed that I have recently committed a bunch of captcha related changes, including a simple captcha module.

    I just thought I’d write a quick post about it as this module makes use of a bit of Elgg functionality which has been around for a while, but that I know a number of plugin developers have missed.

    Namely, the ability to extend actions.

    When the Elgg framework calls an action the Action handler triggers a plugin hook called “action” before executing the action itself. This hook looks like this:

    $event_result = true;
    $event_result = trigger_plugin_hook('action', $action, null, $event_result);

    Where $action is the action being called. If the hook returns false then the main action will not be executed.

    The captcha module uses this to intercept the register and user/requestnewpassword actions and redirect them to a function which checks the captcha code. This check returns true if valid or false if not (which prevents the associated action from executing).

    This is done as follows:

    register_plugin_hook("action", "register", "captcha_verify_action_hook");
    register_plugin_hook("action", "user/requestnewpassword", "captcha_verify_action_hook");

    .
    .
    .

    function captcha_verify_action_hook($hook, $entity_type, $returnvalue, $params)
    {
    $token = get_input('captcha_token');
    $input = get_input('captcha_input');

    if (($token) && (captcha_verify_captcha($input, $token)))
    return true;

    register_error(elgg_echo('captcha:captchafail'));

    return false;
    }

    As you can see, this lets a plugin extend an existing action without the need to replace the action itself. In the case of the captcha plugin it allows the plugin to provide captcha support in a very loosely coupled way.

    Happy coding!

    Wrapping up the week

    May 3rd, 2009 by Marcus Povey

    I just thought I’d write a quick blog post to wrap up the week before heading off to enjoy the May bank holiday sunshine… and what a week it has been!

    The week began with a rather frustrating critical hardware failure on one of Curverider’s servers which took down our community site, SVN and bug tracker among a few others.

    No data was lost, and we were able to get the main sites back online in fairly short order once the new server was hooked up and installed in our datacenter.

    On a lighter note I am very pleased to welcome Leonard Lin to the Elgg team.  Leonard was previously senior hacker at Yahoo and creator of  Upcoming.org. Most recently he has also been involved in the Obama campaign.

    Exciting times ahead!

    And while we’re on the subject of Upcoming.org, I would like to take this opportunity to point you in the direction of the Barcamp Transparency entry on Upcoming. Go sign up now!

    Elgg 1.5 released

    March 13th, 2009 by Marcus Povey

    Gosh! I’ve hardly had a moment to post recently!

    Essentially this is because I and the rest of the Curverider team have been working flat out to get Elgg 1.5 released – which I am very pleased to say has finally happened!

    Both the Curverider team and the open source community have all pulled together and as a result I can honestly say that Elgg 1.5 is the best Elgg yet!

    Elgg 1.5 has loads of new functionality – both visible and under the hood. There’s a brand new theme and dashboard, groups are more powerful, and the whole core has been made much much much faster.

    Almost 800 commits have gone into the core, not to mention numerous commits to plugins – making Elgg 1.5 a lean mean social networking machine.

    More details of what is in this new version can be found here.

    Of course, Elgg 1.5 is a milestone not the final destination… just wait until you see what we have planned for the next version!

    Corrupted downloads via script on IE

    January 5th, 2009 by Marcus Povey

    I have spent the last couple of hours grappling with this problem, and having finally got to the bottom of it I’d thought I’d share my solution.

    Ok, so the problem was that a PHP script which prepared a download (in this case a .zip) from Elgg’s file store was working fine in Firefox but producing a corrupt archive in IE.

    On examining the headers being sent and received I was able to establish that there were two main issues going on:

    1. The zip file was being compressed by mod_deflate, this was being incorrectly handled by Internet Explorer, and so was producing a file which was actually a gzipped .zip file. This is a known issue, and is why Elgg’s .htaccess file only compresses text and javascript.
    2. The code which only permits compression for text mime types was being ignored.

    The reason, obvious with hindsight but not at the time, was this:

    The file was being served by a script, this script modifies the mimetype via header. However, apache was determining whether to compress the file or not based on the initial mimetype of the script – which of course was text/html!

    Once I figured that out, it was fairly simple to solve. I added the following lines to the mod_deflate settings in the .htaccess file.

    SetEnvIfNoCase Request_URI action\/* no-gzip dont-vary
    SetEnvIfNoCase Request_URI actions\/* no-gzip dont-vary

    These lines turn off gzip compression for all actions, while leaving compression running for all other files. This solution is better than turning compression off altogether but it is not ideal, for one if you attempt a script download from anywhere but an Elgg action (which really you shouldn’t be), you will need to modify .htaccess yourself.

    Any better solutions welcome!

    Next Page »
    All content is © Copyright Marcus Povey 2008-2009 unless otherwise stated.