Elgg provides an API for building custom web services. You expose functionality through the web services API by building a plugin and then either publish your API for other developers to build clients or provide your own. Here is a simple example of exposing a method so that a client app can post a status update to the wire in Elgg:

1. Write your function that creates the wire post

function rest_wire_post($username, $text) {
    $user = get_user_by_username($username);
    if (!$user) {
        throw new InvalidParameterException('Bad username');

    $obj = new ElggObject();
    $obj->subtype = 'thewire';
    $obj->owner_guid = $user->guid;
    $obj->access_id = ACCESS_PUBLIC;
    $obj->method = 'api';
    $obj->description = elgg_substr(strip_tags($text), 0, 140);

    $guid = $obj->save();


    return 'success';

2. Expose it

                array( 'username' => array ('type' => 'string'),
                       'text' => array ('type' => 'string'),
                'Post a status update to the wire',

3. Use it

Type this into your browser's address bar making the obvious replacements for your site:


Now, in a real application you would make this a POST request rather than a GET and protect it with user and API authentication. For more information on that see the Elgg web services wiki page.

I've run into the nasty problem that Chrome Frame causes to session handling code that uses the user agent in its security. There are applications that use the user agent string in a hash that sets the signature of a session. Each time the session is loaded using that key, the signature is checked. This catches some session hijacking attempts. Let's assume that an attacker is able to obtain a user's session key and then uses it. There is some probability that the user agent will be different and the attack will fail. It's a layers of security approach - it doesn't prevent the attack but makes it harder. Of course, if the attacker sniffed the session key, the attacker also has the user agent. If the attacker obtain the session key from the user's computer, the user agent was available there also. So you can see that it is not much of a security feature.

There are web applications that use this and this is where Google's Chrome Frame browser addon for IE comes into play. This extension changes the user agent based on the type of data requested and the method of the request. These user agent changes result in the signature check to fail and the session is regenerated (and the user is logged out). Depending on the site and content, this can appear to be almost random or it can be very consistent (log in, log out, log in, log out...).

The solutions are to either drop this security feature or filter the chromeframe string out of the user agent.

Piwik and Elgg

While Google Analytics may be the most popular analytics service, there are times when you want to use your own hosted solution (intranet, control over data). Piwik is a great open source package that provides an impressive set of tools and a very nice look and feel. Using it with Elgg is extremely easy. You can write a plugin to do this in a few minutes as Elgg provides an analytics view in the footer that can be extended.

This is all it takes:

  1. Install Piwik

  2. Create your Elgg plugin skeleton

  3. Create a view to hold your Piwik javascript code - in this case piwik/analytics

  4. Register a callback for the init:system event

  5. In the callback extend the footer/analytics view

  6. Install and activate the plugin

The structure of this very simple plugin looks like this:

Plugin Structure

You can download it here.

Piwik generates its URLs used in links and forms based on data in $_SERVER[]. If you are using a reverse proxy in front of your web server, the incoming request URLS are for the internal server. This results in the people from the outside getting 404 errors after the getting the initial landing page.

To work around this, I was able to use Piwik's boostrap.php file. This is loaded first for any Piwik page. I added some code in there to rewrite PHP's $_SERVER[] parameters to match the original request to the proxy. The variables I had to set were





Elgg Unit Tests

A new component in Elgg 1.7 will be a unit test framework (SimpleTest). I've written a skeleton example of how plugin authors can use the framework. It can be downloaded here.

A little trick that I've learned for debugging a call to the Elgg API that involves a database call is to wrap it with $CONFIG->debug. For example:

$CONFIG->debug = true;
$images = get_entities('object', 'blog', $guid, '', 25);
$CONFIG->debug = false;

This will write the query to the error log giving you a chance to see what you are doing wrong (or if there is a bug in the Elgg framework). Make sure that the global $CONFIG is available within the context. This works fine with versions up to 1.6. Unknown how this will work on 1.7 and beyond.

Update: For Elgg 1.7 and above you need to do this:

$CONFIG->debug = 'NOTICE';
$images = get_entities('object', 'blog', $guid, '', 25);

This assumes that you have debugging turned off. If you have it set to something else (like 'ERROR'), you should set it back to that setting.

This morning Google Analytics wasn't responding. So many sites use it that it basically slowed down the entire Internet.

Someone at work mentioned that Outlook was complaining about an RSS feed. The error message was "The link may not point to a valid RSS source". This was odd because the feed validated and every other feed reader was able to handle it. Even stranger, Outlook had no issues with the same feed if it was not coming from an https address.

After some experimentation, I tracked the problem down to caching. The feed was being generated by a PHP application that was using sessions. By default, PHP sets some http headers to prevent pages from being cached when sessions are used. Outlook 2007 could not handle an RSS feed coming from a server using SSL with caching requested off. The solution was to either turn off session handling when the request was for an RSS feed or change the headers before sent so that caching wasn't turned off. For this application doing the latter was easier.

Recent Comments