25
Sep 13

Fixing UNABLE_TO_VERIFY_LEAF_SIGNATURE

Just a short post as this particular issue took me too long to resolve and I figured it might help some other people.

The problem

When requesting a page from your server via HTTPS with node you get [Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE], but requesting it in your browser works fine.

The fix

This is actually not a node issue. The server you’re requesting a page from has misconfigured their SSL certificates. If your certificate is signed by an intermediate CA you will need to add their certificate (and all others in the chain) to your certificate. This is because node (openssl, really), unlike browsers, doesn’t download any intermediate certificates. You can verify if you’ve configured your server correctly by using COMODO’s SSL analyzer.


24
May 12

User Defined Runtime Attributes in iOS

This is one of those features that seems to have little documentation, isn’t used much yet it can be extremely useful.

I ran into a situation where I wanted to create these custom UIButtons to control an audioplayer. These buttons get reused in a couple of screens and I didn’t wanted to copy and paste the code to change the backgrounds nor did I want two objects.

The solution is to create a single custom UIButton class and use the Runtime Attributes.

#import <UIKit/UIKit.h>
 
@interface AudioButton : UIButton
 
@end
#import "AudioButton.h"
 
@implementation AudioButton
 
// This method will get called for each attribute you define.
-(void) setValue:(id)value forKey:(NSString *)key
{
    if ([key isEqualToString:@"type"])
    {
        if ([value isEqualToString:@"play"])
        {
            [self showPlayUI];
        }
        else
        {
            [self showStopUI];
        }
    }
}
 
// Show the chrome for a play button
- (void) showPlayUI
{
    UIImage *playBackgroundImage = [[UIImage imageNamed:@"UIAlertSheetDefaultCancelButton.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
    UIImage *playPressedBackgroundImage = [[UIImage imageNamed:@"UIAlertSheetDefaultButtonPressed.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
 
    [self setBackgroundImage:playBackgroundImage forState:UIControlStateNormal];
    [self setBackgroundImage:playPressedBackgroundImage forState:UIControlStateHighlighted];
    [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [self setTitle:@"Play" forState:UIControlStateNormal];
}
 
// Show the chrome for a stop button.
- (void) showStopUI
{
    UIImage *stopBackgroundImage = [[UIImage imageNamed:@"UIAlertSheetBlackTransDestroyButton.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
    UIImage *stopPressedBackgroundImage = [[UIImage imageNamed:@"UIAlertSheetBlackTransDestroyButtonPressed.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
 
    [self setBackgroundImage:stopBackgroundImage forState:UIControlStateNormal];
    [self setBackgroundImage:stopPressedBackgroundImage forState:UIControlStateHighlighted];
    [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [self setTitle:@"Stop" forState:UIControlStateNormal];
}
 
@end

Add the custom button to your view by dragging a UIButton onto it and changing its class to AudioButton in the identity inspector. To make the button a play button you’ll need to add a runtime attribute with its key path set to ‘type’ and its value to ‘play’.

That’s all there is to it.


29
Feb 12

U Suck At Coding

Just a couple of weeks ago a fun little project started called ‘U Suck At Coding‘. Essentially, it’s just a mailing list that sends out short programming questions every week. It looks like a fun project so I’ll try to post my solutions here weekly.

This week’s question is the following:

Given two binary trees, tree1 and tree2, determine if they are identical in structure. For example, if tree1 has a root node, a left node, and a right node. tree2 is identical only if it also has a root node, a left node, and a right node. Do not make any assumptions about the tree’s balance, depth, etc. In the image below tree1 and tree2 are identical, tree3 is not.

Here is my (simple) solution.


12
Jan 12

Rooting your Android

A stock HTC Desire's homescreen.

I’ve had an HTC Desire for almost a year and a half now and I was very pleased with it. The stock OS is Android Gingerbread (updated to 2.3.3) with HTC’s own Sense UI-layer on top of it. I was fairly happy with it, it did nearly all the things I wanted it to do, it was practical and didn’t look too bad.

Lately though, I’ve been checking out Android’s latest and greatest: Ice Cream Sandwich (4.0). And UI wise it’s way slicker than previous versions! Now, as you may now, HTC won’t be updating the Desire anymore and suddenly I dreaded staying on 2.3 . I figured what the hell and decided to root my phone.

This was definitely NOT a fun process. iPhone users really get the better experience here. The whole thing involves booting into a special bootloader, wiping certain parts of your memory and than flashing a new ROM. It isn’t the hardest thing to do, but there are a couple of things that can go wrong. So naturally, as a living proof of Murphy’s law, things did go wrong.

On of the aspects of the rooting/flashing process is booting into hboot, which is a special bootloader. This is normally done by holding down volume down and then powering up. I couldn’t do this as my volume down button is nearly broken. No worries though, you can let your device boot into hboot by your computer via usb. So I did this, wiped some memory and flashed the new ROM.

The install was succesfull and I rebooted, I got a really cool animated bootscreen but that was it! It just kept rebooting and never got past the bootscreen. Turned out I forgot to wipe my “user data memory part” (I have no idea what that really is, but hey.. .) I had to get back into hboot, but the usb trick didn’t work anymore as my device wasn’t active long enough. So I had to do it manually. After about 10 tries and lot of cursing/praying to Thor, I got it back into hboot, wiped the memory and flashed again. And it worked!

I now have a rooted device where I can use custom lockscreens, launchers, screenshot apps, anything really. The ROM I used was great for getting me ICS, but not so much from a UI point of view. So I switched NovaLauncher for GoLauncher and installed a couple of minimal widgets and I’m pretty happy with the result.

The whole experience might not be for the feint of heart, but I reckon it’s totally worth it. You get way more control over your device, you can make it look like you want to + you get functionality that should really be standard (the screenshotting for example)


15
Dec 11

Bureaucracy in Belgium

There are probably thousands of examples of how the bureaucratic system in Belgium is slow and sometimes plain annoying.
But here is mine.

Since about 2004 all Belgian politicians and/or officials are required (by law) to submit a list of all their mandates, posts and/or functions to the Belgian Court of Audit (Dutch: Het Rekenhof).
They have to provide the following information about each mandate:

  • The organisation they exercised this mandate
  • The function that they exercised
  • Whether or not this was a payed mandate
  • If this wasn’t a full-year mandate, they have to specify the start and endate.

In the spirit of more transparency and clarity in how our politicians are tied to different entities (be it corporate or not) this is great.
Even better, this is incredibly useful!
Now, all that information gets published in “The Belgian Official Journal” (Dutch: Het Belgisch Staatsblad), which publishes all new legal activities.
This information is available online in the form of a 988 page PDF file. Great right? Everybody has a pdf  reader and can get to the information.

Not quite.
I want to be able to analyse that information set, programmatically. Parsing the PDF file didn’t produce the best results so I figured I just ask for the raw data.

Here is where the bureaucratic system kicked in.
I mailed the Audit Court, explained my problem and asked them if I could get the raw data set from them.
They replied very politely that the law states that the results only need to be published in the Belgian Official Journal (BOJ) and that I should probably contact them.

Now, the online presence of the BOJ is just a couple of Perl scripts, it doesn’t hold any online contact information.
I mailed to the Department of Justice in stead, as this holds the BOJ; they were able to refer me to the correct person.
I got told that the BOJ only offers publications in PDF, if I want any other format I should contact the creator of the original document.
In this case that would be the Audit Court.. who had just told me to contact the BOJ.

So there you have it. It’s a bit ironic really. A law that clearly aspires to be more open and forthcoming as a government and you get these kind of things. This all happened last year and I got so disillusioned from it, that I just dropped the entire project.

PS: I’ve contacted Peter Dedecker (Flemish rep) about the issue, maybe he can force something to be done.

 


16
Oct 11

CloudApp Java wrapper

This post just serves as a shameless plug for the Java wrapper I wrote about a year ago.  The original plan was to create an Android app using the CloudApp API as a way to learn the Android SDK. I sort of got bored halfway trough but had already written the wrapper. Instead of ditching the thing entirely I decided to clean it up a bit and release it in the open.

I just updated it so it covers all the new functionality exposed via the CloudApp API. It now also returns proper class models instead of JSONObjects.

Info:

Cheers!

15
Sep 11

Piston: Workaround for requests with a parameter in the Content-Type

I ran into an annoying bug where all my ajax requests from Firefox ended up in 400 Bad Request, yet Chrome was totally fine.
The difference is the Content-Type header that gets sent in the request. Firefox uses

Content-Type: application/x-www-form-urlencoded; charset="utf-8"

whereas Chrome sends

Content-Type: application/x-www-form-urlencoded

Both are perfectly valid yet the first one leads to errors. It turns out this is an old issue (almost 2 years now!) for Piston.

The issue here is that depending on the Content-Type header, Piston will try to parse the incoming parameters. If you send ‘application/json’ it will interpret the incoming data stream as a JSON object, parse it and make it available at request.data . Unfortunately it tries to parse if the Content-Type is not ‘application/x-www-form-urlencoded’. All of this happens internally, so there is little we can do there.

However, since you most likely already have an authenticator in place, you can completely modify the request object before any parsing happens.

class MyAuthentication(object):
    def is_authenticated(self, request):
        self.check_content_type(request)
        return self.check_authenticated(request)
 
    def check_authenticated(self, request):
        # Implement your own authentication checks here.
        # Don't forget to set the request.user object!
        return true
 
    def check_content_type(self, request):
        ct = request.META.get('CONTENT_TYPE', None)
        if ct:
            request.META['CONTENT_TYPE'] = ct.split(';')[0]

Another option would be to override the __call__ method of the Resource class you use in urls.py

Coincidentally, when I published this post, an announcement was made on the Google Groups that there is a new developer for django-piston, so this might get fixed pretty soon!


04
Sep 11

Easy deployment with Fabric

As mentioned in my previous posts, I updated my main www page and have been working on some other small web projects. Usually my process for these kind of things goes something like this:

  1. Edit file locally
  2. Try it out locally (in the browser if it’s a UI change)
  3. Run tests to make sure I didn’t break any old behaviour
  4. Prepare for deployment (mostly minifying)
  5. Open up Cyberduck (an OS X ftp,ssh,.. client) and upload the new files to the server

There is nothing really wrong with that kind of setup, but it gets tedious quite fast and tends to lend itself to skipping step #3. Step #4 and #5 can be quite cumbersome really. Especially the whole upload/overwrite/confirm dialog boxes are annoying and lead to doing it live on the server.

I decided to do things ‘the right way’ and settled down on the following approach:

  1. Edit file locally
  2. Try it out locally (in the browser if it’s a UI change)
  3. Commit the changes and push them. (git)
  4. run ‘fab deploy’

There are a couple of things which are much better with this approach (IMHO).

  1.  I’m now using source control. Kind of an obvious improvement.
  2. I can do all my changes from the terminal, no need for a third party app like Cyberduck.
  3. Running tests, preparing for deployment is now all done by Fabric
  4. I can deploy to multiple servers with just the fab deploy command.

All the magic happens by Fabric. It’s nothing more than a python file which executes some bash commands over ssh (or locally).
Here’s (an abbreviated version of) the fabfile.py for my domain:

1
2
3
4
5
6
7
8
from __future__ import with_statement
from fabric.api import run, env, cd
 
env.hosts = ['gaeremynck.com']
def deploy():
with cd('/var/www/gaeremynck.com/build'):
    run('git pull')
    run('ant build')

I’m using HTML 5 Boilerplate which includes a build directory from where you can minify all your assets (css, js, html, ..) and other various optimizations. When all of that is done, the minified content gets dumped in the published directory. I’ve symlinked my htdocs folder with that published folder. So once the build is done, my site is updated.


27
Aug 11

jQuery Lifestream and followmy.tv

I’m a big fan of doing as much as possible client side and I’ve been following Christian Vuerings his ‘Lifestream‘ plugin for a while now. It shows you a stream of your online activies and does this all in Javascript. (Well, technically it relies quite heavily upon Yahoo!’s YQL so there is a server involved for communication and some basic filtering.) The actual mash-up is fairly straightforward, it’s just the last x items (date based) that should be shown.

In between studying for my exams I got bored and decided I need a new front page for my www domain. My last one was from 2 years ago when I needed a portfolio for an internship. The old site wasn’t that bad, but it wasn’t snazzy either. It was all static HTML with a couple of screenshots of what I had created so far. As a portfolio I think it sufficed. But since I’m not in looking for work right now, I decided I should put up something different.

Enter Lifestream.

I pulled down the latest html5boilerplate goodies, downloaded a copy of the lifestream plugin, configured it (which is stupidly simple) all in under 20 minutes. Most of that time was spent dealing with trying to improve on the ‘design’ (I decided to go with the old simple-is-more-and-I-shouldn’t-attempt-design-ever credo.)

I was pretty content with how easy it was to support:

  • Foursquare
  • Github
  • Google Reader
  • Last.FM
  • Reddit
  • Stackoverflow
  • Twitter
  • My blog (I had to create a small patch to the lifestream-wordpress ‘service’, I’ll send a pull request in a bit! – Merged in)
But then I got bored again! I wrote the reddit service when I got bored during my previous exams, so naturally, I had to create one now. Another social media site I use a lot (and that I find actually useful!) is followmy.tv. You can keep track when shows are airing, which episodes you’ve seen, comment, …
One problem though, they don’t have an API or XML feed. I asked the developers on twitter, but they haven’t responded yet.
So I did the obvious next thing, screen scrape! Using YQL it’s getting way easier to do these kind of things.
select * from html where url="http://followmy.tv/u/simong" and (xpath = '//div[@id="recent-eps"]/ul/li' or xpath = '//ul[@class="activity-feed"]/li')

is the query to get the recent episodes you watched or your general activity stream (loved a show, followed a new show, etc…). The results are returned to you via jsonp (which is all nicely encapsulated by jquery, so you don’t really need to care about the how)

Now that I’ve got the actual activity stream in json, it’s fairly easy to parse out the right content and sticking it in the big stream. If the followmy.tv devs don’t respond in the next couple of weeks I’ll clean up this service and send Christian a pull request so this ends up in the main repo.

In the meantime, here’s what I’m using right now:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
$.fn.lifestream.feeds.followmytv = function( config, callback ) {
    var parseDate = function(s) {
        var d = new Date();
        if (s.match(/[0-9]{1,2} minutes? ago/)) {
            var m = parseInt(s.replace(/\D/, ''), 10);
            d.setTime(d.getTime() - m*60*1000);
        }
        else if (s.match(/[0-9]{1,2} hours? ago/)) {
            var m = parseInt(s.replace(/\D/, ''), 10);
            d.setTime(d.getTime() - m*60*60*1000);
        }
        else if (s.match(/[0-9]{1,2} days? ago/)) {
            var m = parseInt(s.replace(/\D/, ''), 10);
            d.setTime(d.getTime() - m*24*60*60*1000);
        }
        else if (s== 'Just watched') {
            d = new Date();
        } 
        else {
            d = new Date(s);
        }
 
        return d;
    }
 
 
    var parseRecentlyWatched = function ( input ) {
        var output = [];
        for (var i = 0, j = input.results.length;i < j; i++) {
            var $p = $(input.results[i]), o = {'config': config};
            if ($("div", $p).length > 0) {
                // Something you watched.
                var time = $("div.time", $p).text(),
                    d = parseDate(time); 
                o.html = "watched " + $("div.desc", $p).html();
                o.date = d;
            } else {
                // Recent activity bar.
                var time = $("span", $p).text();
                var d = parseDate(time);
                $p = $p.remove("span");
                var s = $p.text().replace(config.user, "").replace("You are ", "").replace("You ", "");
 
                o.date = d;
                o.html = s;
            }
            output.push(o);
        }
        return output;
    };
 
    $.ajax({
             url: $.fn.lifestream.createYqlUrl('select * from html where ' + 'url="http://followmy.tv/u/' + config.user + '" and ' + '(xpath = \'//div[@id="recent-eps"]/ul/li\' or xpath = \'//ul[@class="activity-feed"]/li\')', 'xml'),
             dataType: "jsonp",
             success: function ( data ) {
               callback(parseRecentlyWatched(data));
             }
           });
};

16
Aug 11

AppleTV and XBMC

Couple of months ago I bought an Apple TV for my parents. They needed something to display their pictures and watching a movie on the TV. Hooking up a laptop was a bit too much of a hassle (and frankly their not technology-savy enough to pull that off.) So Apple TV seemed like a good fit. Knowing Apple, I thought that my parents would manage just fine once everything was setup and the price wasn’t that high so I just bought the thing without looking for something else.

I probably should’ve looked into it a bit more because sharing movies or music only works via ‘iTunes Home Sharing’ and that was something I didn’t want to get into. Somebody pointed out that you could run XBMC on iOS nowadays so I gave that a try and boy was I glad I did! XBMC does everything you could want from a media center and then some!

Installing it requires you to do three things.

  1. Jailbreak your Apple TV (this might void your warranty, so proceed at own risk..)
  2. Install XBMC
  3. Disable auto updates (skip explanation)
Following these two guides will create a working XBMC on AppleTV setup. There is only one thing I highly recommend and that is ‘turning off automatic updates’ for the iOS platform that is running on your AppleTV.  In fact you will probably have to do it anyway or you’ll only get about 5 minutes worth of XBMC before it shuts down.
Here is what’ll happen if you don’t.
  1. You start up your AppleTV
  2. You go into XBMC
  3. After ~5 minutes, iOS (the underlying operating system) will check for an update and try to display the ‘Update now or later?’ dialog.
  4. Only it can’t do that, because XBMC is running. iOS will send a kill signal to XBMC and XBMC will shut down.
  5. Now, the natural thing to assume would be that you get thrown back to FrontRow (the ‘normal’ skin you see when you start your AppleTV). But for some reason that doesn’t happen. The thing crashes and reboots.
Now, if you don’t know this, you’ll just assume your XBMC install isn’t working.. BUT IT IS! It took me a long time to realize and once I did the fix was easy.
We’re not going to turn off automatic updates, we’re gonna trick iOS into thinking there are none. iOS tries to determine if there is an update by checking a couple of websites. If we redirect those requests to nowhere, there is ‘no update’.
Here is what you need to do:
  1. ssh into your AppleTV (just like you did in the XBMC install procedure)
  2. Type in these 4 commands and hit enter after each line:
    echo “127.0.0.1 mesu.apple.com” >> /etc/hosts
    echo “127.0.0.1 appldnld.apple.com” >> /etc/hosts
    echo “127.0.0.1 appldnld.apple.com.edgesuite.net” >> /etc/hosts
    echo “” >> /etc/hosts

  3. Restart your AppleTV device
That should leave you with a fully functioning XBMC setup. Once you’ve added the shares to your library, you’re pretty much done.