2008 In Retrospect

Christer inspired me to have a look back on what happened on the blog during 2008, so I’ve compiled a list of numbers, posts and other (non-)interesting information around the blog. The most significant thing is probably that I actually started the blog in April 2008, so I’ve just finished the first year of actually blogging.

Key stats:

  • Posts: 161
  • Comments: 89
  • Hits: 242781
  • Unique: 18882
  • Spam caught by akismet: 2596
  • Most spammed month: November
  • Technorati Authority: 13
  • Technorati Rank: 454.532
  • Reactions registered on Technorati: 51
  • Incoming links (to e-mats.org) on Google: 29
  • Incoming links (to e-mats.org) on Google Blogsearch: 23

Most popular referers:

  • google.com
  • search.live.com
  • en.blog.wordpress.com
  • google.de
  • google.co.uk
  • google.co.in
  • dagbladet.no
  • google.ca
  • google.fr
  • blog.vincentlaforet.com
  • cogo.wordpress.com
  • google.nl

Most popular posts:

I have no idea why the 77 things post is the most popular. The Tortoise post solves an issue people are using google to find information about, the same with the ssh_exchange_identification post. The WordPress post got some publicity in the comments on the WordPress blog (and a trackback or two from my other WordPress posts). An intersting thing is the popularity of Swoooosh, which I made as an exercise in programming with Flex. There seems to be a great demand for another free, completly open source flash file uploader, so I’d suggest that someone took the project further — and hooked up a Google Code page for it.

The year ended with the release of Keepitclose – a PHP based caching solution, which was my first project on Google Code. It was a fun project to do, and we’re putting it into production during the first weeks of 2009.

Other important things of 2008 was the library that Christer and I’ve been developing. We’ve not released any products based on it yet, but it has been a great exercise in developing and structuring code for reuse. Hopefully we’ll see a release during 2009.

I’ve spent the last week updating the pwned.no code base, and I’m planning an updated release during this week.

The biggest thing of 2008 on a personal note was that we finally got ourselves a brand new house, which we moved into at the 30th of november.

I’ll leave you with wishing you a Happy New Year (if you’re following the same calendar as I am), and hopefully the new year will bring loads of interesting projects and great news!

    Merry Christmas and Happy Holidays!

    Tomorrow is Christmas Eve, the day that we usually celebrate christmas on in Norway. I’ll spend the first four hours of the day at work selling Hi-Fi (as I’ve been doing the last ten days (each single one of them)) at my brother’s store, before visiting my family for the christmas dinner and exchanging of gifts.

    I plan spending the rest of the time until returning for work on the 5th of january hacking on some old code for pwned.no and a few other relevant projects.

    Anyways, just wanted to wish all readers stumbling across this page all the best for the year to come, and please, stop the holocaust! (on a side note, our christmas tree even got a name this year: Svein. Might not be a good idea when we’re supposed to throw it out, but it could turn out to be a new tradition..)

    Bend over and take it! -Valve

    Valve has decided to switch Norwegian customers over from the U.S. dollar to the euro; in itself a minor move which just requires us norwegians to multiply with another number when converting the price to Norwegian kroners. Here’s the catch, though: They kept the same numeric price. So anything that cost $49.95 a couple of days ago, costs €49.95 today. Converted to Norwegian kroners, that’s a price increase of over 45%! It’s now cheaper to buy the game in the store, get the box, the manual and everything than purchasing it over Steam.

    This sounds like bad news, but it actually opens up the market a lot for the OTHER great services such as gamersgate, gog and other digital content providers, as they suddenly has a lot more competitive pricing. I had no problem paying a dollar or two extra for keeping my games in Steam, but now we’re talking 50% or more just to get it in Steam. Not going to happen.

    A few Keepitclose Updates

    I’ve added a few new features to the Keepitclose code base. The cached version of the resource now also keeps — and reproduces — the headers from the original resource. That will allow text/xml to work as it should, in addition to keeping encoding information and other vital parts of the information contained in the HTTP headers. I’ve also added urlencode() support to the path identifier of the request, so that we’re able to handle requests which feature UTF-8 and other encodings in parts of the URL.

    I have a few other features in the pipeline too, but I’m not sure if I’ll find the time to add them until after the weekend. Be sure to do a svn update if you’ve checked out the code!

    Releasing Keepitclose Alpha

    I’ve just created a small project site over at Google Code for Keepitclose. Keepitclose is a HTTP local caching web service written in PHP meant to cache resources retrieved from external and internal web services. It currently supports both an APC backend (using shared memory in the web server itself) and using Memcache (which allows you to have several frontends using one or several backend memcache servers).

    Missing features are currently:

    • Keeping HTTP headers
    • Adding cache information to HTTP headers
    • A file based backend
    • Everything else you can think of

    The server do however support:

    • Time to live (TTL) for a cached resource when stored
    • TTL Window, i.e.:

      A new version should be fetched at regular intervals, such as every sixth hour. New data are available at 00:00, 06:00, 12:00 and 18:00. Use ttlWindowSize=21600 to get six hours window size. Use ttlWindowOffset to add a offset; ttlWindowOffset=900 adds fifteen minutes to the value and retrives new content at 00:15, 06:15, 12:15 and 18:15.

    If you want to implement your own backend, implement the Keepitclose_Storage_Interface and add an entry into the config.php file for your module, i.e. ‘file’ => array(‘path’ => ‘/tmp’).

    The current version also supports simple access control using the allowedHosts entry in the config file. This entry contains one row for each allowed host as a regular expression:

        'allowedHosts' => array(
            '^127\\.0\\.0\\.1$',
        ),
    

    .. will only allow requests from localhost. To allow a subnet, you could write ‘^127\\.0\\.0\\.[0-9]+$’.

    You can also add several memcache servers, a request will then poll a random server to retrieve the resource. If not found, the content will be retrieved from the web and stored to all memcache servers. This is useful for environments with a very heavy read load.

    'storage' => array(
        'memcache' => array(
            array(
                'host' => 'tcp://127.0.0.1',
            ),
        ),
    ),
    

    To add more memcache servers, simply add another array() of memcache entries:

    'memcache' => array(
        array(
            'host' => 'tcp://127.0.0.1',
        ),
        array(
            'host' => 'tcp://127.0.0.2',
        ),
    ),
    

    You can also set ‘port’ and ‘persistent’ for the memcache connections.

    Please leave a comment here or create an issue ticket on the google code page if you need any help or have any suggestions. All patches are welcome.

    Experiences with the Netgear ReadyNAS NV+

    As part of the new multimedia setup here at our new house, I decided I had to get a new NAS to keep my media files safe and stored somewhere which didn’t require a complete computer running (to save power and keep the noise a bit down). As I’m using the Squeezebox (v2) as my main source for playing music, the ReadyNAS from Netgear seemed like a good choice as it’s the only NAS on the market with the Squeezecenter (the server software for the Squeezebox) integrated into the appliance itself. A bit pricey, but it has proven itself to be of good value.

    People were very amazed with what the Drobo could do, but as they only deliver USB / Fireware disks that need a host computer, they were out of the equation early on. I was however very impressed by the ReadyNAS and it’s no-disk-configuration-needed-we-just-raid5-and-journal-it-for-you approach. Netgear uses their own X-RAID configuration which allows you to shrink and grow the raid as time goes by, and the NAS configured itself to a RAID5 like structure. The web interface to the appliance has been a bit wobbly at times, but I think this is just because I were a bit impatient with getting everything up and running. It even runs on gigabit ethernet, so it’ll be a great storage location for all digital media here. Recommended!

    Oh Updates Where Art Thou?

    It’s been a while since I’ve updated the blog, but fear not, it’s all for a good reason. During the last three weeks I and Anette has purchased — and moved into — a new house! We’ve settled down in Hvaler, Norway, almost all the way out into the ocean. I’ll try to get some pictures up on my flickr page later, but most of my time is consumed by boring tasks like running cables for UTP through the walls, trying to get the telephony cable where it’s supposed to be etc. The house is brand new and we’re doing the second floor ourselves (or, at least my dad is. I’m not very useful in this situation).

    What I’ve learnt so far:

    • Be sure to unwind and straighten out the UTP / ethernet cable from the roll before trying to get it through a 16mm plastic pipe. It gets very difficult to pull it after a while otherwise…
    • Getting a UTP cable through a 40mm pipe is harder than it looks when you have corners with edges. Yes. The pipe is very, very wide. The cable is not. It favours getting stuck at the beginning of the last corner long inside the wall.
    • 802d pwns.
    • My 32 inch TV is way too small. Good thing a new one is on the way.
    • The people that invented zones for DVD movies should be ashamed. My movie collection is a mixture of zone 1 and zone 2 movies, and while attempting to play them on my Xbox 360 today, I had to go through three movies before I found one with the correct zone. People who download movies from questionable sources NEVER have these issues. Why do the products I have paid for have FAR MORE problems and frustrations than those which people get for free?! THIS IS NOT ACCEPTABLE.

    But other than that, we’re finding ourselves more and more familiar with this place, and it’s great to finally have our own house. Induction rocks.

    Patching Zend_OpenId To Maintain Error Messages

    To help anyone else in their quest to implement Zend_OpenId in their code, I’ve created a small patch against trunk which adds error internal error messages in most places where there’s a return false;. This should help when debugging your code, both if you’re implementing an authentication service and use Zend_OpenId as a consumer or if you’re implementing just the consumer part of the equation.

    I’ve uploaded the diff: Consumer.php.patch (Consumer.php.patch.txt).

    The only thing that seemed a bit weird was that one of the error messages that were present in 1.6.0 had been removed in trunk:

    if ($status != 200) {
        this->_setError("'Dumb' signature verification HTTP request failed");
        return false;
    }
    

    I’ve readded this message in my patch, but I feel that the error message should be something like:

    $this->_setError("The server responded with HTTP status code: " . $status);
    

    instead.

    Oh well. Hopefully someone will find this useful.

    Adventures in OpenID and Zend Framework

    I’ve been toying around with OpenID and the Zend Framework for a night or two now, and I’ve made a few experiences I thought I should share with the intarwebs (now, that’s probably the point where you should make the decision to stop reading for most blog posts). Quite some time has passed since I last had anything to do with OpenID, so just getting up and running was a challenge.

    An OpenID identifier is usually represented by an URL (such as https://me.yahoo.com/<login>), which the OpenID consumer then contacts to get information about how to communicate with the OpenID identity provider (Yahoo! in this case). The consumer contacts the provider, gets an URL to redirect the client to, and receives notice after the client has authenticated with the provider.

    First I’d like to say that OpenID seems to be too hard to use for any other than those who have a particular interest in it. I have a Yahoo! account and a Google Account, which both can be used for OpenID authentication. I have no idea how I use my Google Account for this, without having to provide endpoints manually. Ugly.

    I did at least get the Yahoo! authentication working, but I’m still undecided on wether I’m going to implement OpenID support in any current project. Possibly. We’ll see.

    Anyways, my implementation in Zend Framework is mostly a copy of the tutorial in the ZF manual, but there is one important point that they do not mention: In the standard installation, you have to use Zend_Session to handle your sessions. That means calling Zend_Session::start() instead of session_start(), as Zend_Session cannot be used after a session has been started. This dependency kind of killed my enthusiasm, as we just pull the parts of Zend Framework that we need into our project as thing progresses. Changing how we use sessions is a bit too much to ask. Luckily you can still use $_SESSION as usual after starting Zend_Session, but sitll. Not too fond of that. I hope that it will be decoupled some time in the future..

    Testing code:

    require_once 'Zend/OpenId/Consumer.php';
    
    $consumer = new Zend_OpenId_Consumer();
    
    if (!empty($_POST['openid_identity']))
    {
        if(!$consumer->login($_POST['openid_identity']))
        {
            die("OpenID login failed.");
        }
        else
        {
            print('We logged in!');
        }
    }
    
    if (isset($_GET['openid_mode']))
    {
        switch($_GET['openid_mode'])
        {
            case 'id_res':
                $consumer = new Zend_OpenId_Consumer();
                $id = false;
                
                if ($consumer->verify($_GET, $id))
                {
                    $status = "VALID " . htmlspecialchars($id);
                }
                else
                {
                    $status = "INVALID " . htmlspecialchars($id);
                }
    
                print($status);
                break;
    
            case 'cancel':
                print("someone pressed cancel!");
                break;
        }
    }
    

    Switch out $_POST[‘openid_identity’] with your OpenID identifier (the whole URL), and you should be all set.

    If you keep getting failed logins without a redirect, check that you have https support in PHP through openssl (the module is named php_openssl). Zend Framework provides no hint that this can be a problem, but after stepping through the source (I’m test driving NetBeans 6.5) the solution became apparent.