Skip to content


rev=canonical (for PHP)

The past days people who are concerned about the fitness of the web have been abuzz over the concept of shortening URLs via the rev=”canonical” concept. The idea behind it is that resources on the web provide a hint about their everlasting short URL by means of adding a tag like <link rev="canonical" href="http://myshort.url/xyz123" />.  The concept has its own blog with plenty of information.

I’m contributing my part to this in the form of a small shortening implementation for PHP 5.3.  It is available under a BSD license over on github.

Posted in Tech, Web Development.

gpsbabel pain

As I wrote back in November, I’ve successfully managed to connect my ancient Garmin GPS device to my Macbook Pro using a Serial-to-USB adapter thing and the gpsbabel tool. “Successfully” is a bit of a stretch here, because gpsbabel sometimes acts wonky and refuses to play nice. Following are the lessons I learned recently.

  • If gpsbabel tells you “[ERROR] A800_Off: Not acknowledged“, ignore it. In most cases, the import will still work. If it doesn’t, try again.
  • If gpsbabel tells you “GARMIN:Can’t get waypoint from /dev/cu.usbserial“, try again until it works. I suspect this has something to do with the way to GPS adapter, the OS X driver stuff and gpsbabel interact: Sometimes the device is sort of not registered with the operating system and things fail. Seconds later it works again.
  • The same applies for the error “GARMIN:Can’t init /dev/cu.usbserial“. Try again or if it refuses to work after let’s say a dozen attempts, unplug and reconnect the adapter to your computer.

As you see, repeatedly launching gpsbabel helps a lot. Go figure.

To ease the importing, I’m using the following shell script:

#!/bin/sh

TODAY=`date +%Y-%m-%d`

if [ "$1" = "tracks" ]
then
        ~/bin/gpsbabel -t -i garmin -f /dev/cu.usbserial -o gpx -F $TODAY-$1.gpx
else
        ~/bin/gpsbabel -w -i garmin -f /dev/cu.usbserial -o gpx -F $TODAY-$1.gpx
fi

Call it either as “./import.sh waypoints” or “./import.sh tracks“, depending on what you want to load from the device.

Posted in Tech.

Hacking Status

Below are the results of sitting down today for an hour or so and catching up on some of my code hacking projects.

PEAR related:

Other hackery:

Some days ago I committed an implementation of Bloom Filters for PHP to GitHub.  Bloom filters are pretty handy data structures when you need to quickly figure out if something has been processed before and when false positives are not a problem.  This means that sometimes the filter will tell you that item X hasn’t been processed earlier when in fact it has.  On the other hand, if the filter tells you that an item has already been processed, this is definitely true. There is no documentation at the moment, but the code comes with extensive PHPdoc comments and there is a unit test in the repository that covers all the functionality and provides a good starting point.If you are interested in retrieving the code via git, use this:

$ git clone git://github.com/mj/php-bloomfilter.git

Or fetch it from the web interface. The code is released under a BSD license, so you can pretty much do whatever you like with it.

On a somewhat related note this was the first time I used git, and I seem to like it.

Posted in hacking status.

Lutz Heilmann

[When redoing this site, I decided to not blog about politics. I need to make an exception today because there is a serious issue that needs to be made aware of.]

You know, there are some people who just don’t get it. The Internet Thing that is.

Some people don’t get it because they are old. Like 100 years old or something. Some people don’t get it because they don’t need it. Like those living on the moon or something. And some people don’t get it because they are politicians. Like Hans-Christian Ströbele, Wolfgang Schäuble, or Lutz Heilmann.1

Hans-Christian Ströbele doesn’t own a computer at all2 and Wolfgang Schäuble thinks the Internet is solely a place for terrorists and other public enemies to hang out and share their plans for world domination. And now Lutz Heilmann. Dear lord, where should I start? This week he forced the German chapter of the Wikimedia Foundation by means of a restraining order to take down the redirection from wikipedia.de to de.wikipedia.org because his Wikipedia article contains facts about his past that he contests.

He must be joking, right? Taking down the link brings him nothing but mock and malice. The redirection is gone but the article is still there and will be there forever and the news about Heilmann’s silliness is in all tubes today. So he gained nothing and ridiculed himself to no avail, because he doesn’t get it.

And guess what? Those people are leading the country I’m living in. They are in charge of our future. Some people rely on them to fight global warming, the financial crisis, fix the education system, and maintain the democracy. And all that without them understanding a major portion of the mass media. Won’t work.

  1. All of them are members of German Bundestag. You’ll find people like them in the government of your country, too. []
  2. German-language video, sorry []

Posted in politics. Tagged with , .

Garmin USB devices and OS X

I have one of those Garmin GPS devices (eTrex Vista to be precise) lying around. Ever since I switched to a Mac full-time I have been unable to make any use of it because the cable to connect the eTrex to a computer supports RS-232 only, which is not supported by most modern machines. Some time ago I bought a cheapo Serial-to-USB-adapter, but was unable to get the device working with that one.

Turns out that most adapters don’t implement the full range of RS-232 features as required by GPS devices. Who knew? Garmin itself sells known-to-work adapters, but they cost around 50 €, which I find a bit hefty for just hooking up a five-year old GPS device for occasionally playing with it. But there is a much cheaper solution available: The Gilsson Serial to USB DB9 Adapter is specifically made with Garmin GPS devices in mind and works like a charm on OS X. On top of that, I got mine from Germany-based Globetrotter for as little as 20 €. (The catalog price is $44.95 though, so your mileage may vary depending on where you live.)

On the software side I have so far only used gpsbabel, which works well if one is only interested in extracting tracks and waypoints as GPX files. (One can import them into other software like e.g. Google Earth.) Garmin offers a bunch of OS X software for their devices, too.

Climbing Grades Cheat Sheet

If you are into this rock climbing thing as much as I am, you have probably noticed that there a gazillion different grading systems for describing the difficulty of climbing routes.

People in Europe mostly use the UIAA and the French grading schemes (but some parts of Germany and the Czechs have their own), unless they live in Great Britain where a different scheme is in use. Climbers in the US use their own popular scheme to rate their climbs.  So do climbers in Norway, Australia, Brazil, Finland and South Africa. I’m sure there are more, but these are the ones I know of.

And if you are into bouldering (short climbs without a rope on large rocks), you have to remember another two grading schemes. Fun, huh? But it only just started: We have another grade for ice climbing, one for alpine climbing (think of the north face of Eiger, Matterhorn and the like), and a third one used when rating aided climbing.

Unless you are a total genius, it is impossible to remember all the schemes (or even the important ones), let alone to remember how they compare to each other.

Fear not, help is on its way. Based on information from Wikipedia, I compiled a little cheat sheet that lists all of the above schemes and puts them in comparison. I made the sheet to the best of my knowledge and I think it is accurate. Should you spot any errors, leave a comment.

Posted in climbing. Tagged with .

Importing Delicious Library into LibraryThing

Today I have started evaluating LibraryThing as a possible (more social and webbish) alternative to Delicious Library. In the course of this I attempted to import my books from Delicious Library into LibraryThing as suggested by their import guide, but failed miserably: My books all showed up in my catalog but none of the had their ISBN attached, which resulted in cover images not being loaded etc.

Apparently LibraryThing’s Universal Import feature works by scanning a given file for ISBNs, which are then added to the catalog. In case it cannot find ISBNs, it seems to fall back to some other mechanism for at least extracing title and author information from the given file.

Instead of trying to figure out why LibraryThing was unable to import my data, I came up with a simple solution that exports a Delicious Library into a text-based format that Universal Import can safely consume. Because Delicious Library uses XML to store its catalog, one can throw basically any programming language with XML support at the problem. I went for PHP today, because it has a nice object-oriented interface to Delicious Library (maintained by yours truly):

<?php
/* Use this script to convert the Delicious Library data to a format that
 * can safely be imported into LibraryThing.  Contrary to the documentation,
 * LT does not support importing Delicious Library directly.
 *
 * Usage: $ php dl-to-lt.php > export.txt
 *
 * Use export.txt in the Universal Importer thing.
 */
require_once "File/DeliciousLibrary.php";

$library = new File_DeliciousLibrary("/Users/martin/Library/Application Support/Delicious Library/Library Media Data.xml");

try {
    $library->parse();

    foreach ($library->getBooks() as $book) {
        if (empty($book->asin)) {
            fwrite(STDERR, "Unable to export book \"" . $book->title . "\" because ISBN is missing.\n");
            continue;
        }

        echo $book->asin . "\n";
    }
} catch (File_DeliciousLibrary_Exception $e) {
    die("Uh oh, something went wrong. Go figure: " . $e->getMessage() . "\n");
}

Works For Me[tm].

Posted in Tech.

Django settings files for development and production

Django LogoWhen developing projects with Django, one usually uses at least two deployments of the project: One for developing things and another for the production site.

Let’s assume that the development deployment resides on your local computer in the directory /www/project and can be accessed via http://localhost:8000/. The production site uses Apache and mod_python, is available at http://project.tld/, and lives in /var/www/sites/project.

In such a situation it is common to have different Django settings files for each deployment — it’s safe to assume that paths on your local machine are different than paths on the production server, that another database (think of SQLite on the development host and MySQL in production) or at least other access credentials are used, and so on.

I found that implementing the above requirements in an easy to reproduce and convenient manner in Django is everything but trivial (at least for me), which is why I decided to write up how I did it.

Step 1: Make sure Django is installed properly

By properly installed I mean that Python knows where the Django packages are. Fire up an instance of the Python interpreter interface by invoking the command python on your shell.

localhost:~$ python
Python 2.5.2 (r252:60911, Sep 22 2008, 14:42:43)
[GCC 4.0.1 (Apple Computer, Inc. build 5250)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>>

No error means: Good.

(You might have noticed that I’m using OS X here. This does not really matter because the ideas and concepts presented below work on any other UNIX flavor as well. They should work on Windows as well.)

Step 2: Development deployment setup

On the development machine I want to use the development server that ships with Django. It’s easy to use, light-weight and, in contrast to Apache, automatically reloads Python code for each request, which is very convenient for development. (Speaking of which, I have never understood why Python does not automatically
notice that code changed in the Apache deployment.  Come on people, other scripting languages have been supporting this ever since.)

The Django settings file for the development setup resides in /www/project/settings/development.py:

localhost:/www/project $ ls -1 settings/
__init__.py
development.py

Django itself places the settings file in /www/project/settings.py when creating the project. When moving it to a subdirectory, make sure to create an empty __init__.py in there. In my case, I did exactly this and removed the default settings.py file.

Now when you try to run the development server, it actually looks like something might work:

localhost:/www/project.tld $ python manage.py runserver
Validating models...
0 errors found

Django version 1.0-final-SVN-unknown, using settings 'settings.__init__'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

As you can see, Django thinks that the settings can be found in settings/__init__.py. When retrieving http://localhost:8000, you’ll see that this totally does not work. Who would have thought?

When attempting to start the server using django-admin.py, things get even worse:

localhost:/www/project $ django-admin.py runserver
Error: Settings cannot be imported, because environment variable
DJANGO_SETTINGS_MODULE is undefined.

At the same time, this gives us a valuable hint: The DJANGO_SETTINGS_MODULE environment variable can be used to point Django to the settings file that should be used:

localhost:/www/project $ export DJANGO_SETTINGS_MODULE=project.settings.development
localhost:/www/project $ django-admin.py runserver
Error: Could not import settings 'project.settings.development' (Is it on sys.path?
Does it have syntax errors?): No module named project.settings.development

Still no luck, but a different error message this time. The problem now is that Python has no idea from where to load the file. It uses some predefined directories in the sys.path variable to search in when interpreting import statements, but none of them contains settings/development.py.  This can be easily solved by setting the environment variable PYTHONPATH to the parent directory of our project, i.e. /www:

localhost:/www/project $ export PYTHONPATH=/www
localhost:/www/project $ export DJANGO_SETTINGS_MODULE=project.settings.development
localhost:/www/project $ django-admin.py runserver
Validating models...
0 errors found

Django version 1.0-final-SVN-unknown, using settings 'project.settings.development'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

There you go: Now the development server is using the correct settings file. In the next section the Apache setup for the production site is explain.

Update: I received an email from someone who told me that, after settings PYTHONPATH to /www, django-admin.py claimed it could not find the django.core package anymore. The problem could be solved for him by setting PYTHONPATH to /directory/to/django:/www. I cannot reproduce this with my setup though.

Step 3: Production deployment setup

With the findings from the previous section, configuring Apache and mod_python is a lot easier than one might think. Basically the same tasks as earlier for the development server need to be done: First tell Apache which configuration file should be used. For the production setup this is settings/production.py. Then tell Apache where to look for production.py. Earlier this was done via the PYTHONPATH environment variable — mod_python employs a similar mechanism:

<VirtualHost *:80>
DocumentRoot /var/www/sites/project
ServerName project.tld

<Location />
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE project.settings.production
PythonPath "['/var/www/sites'] + sys.path"
</Location>
</VirtualHost>

The SetEnv command populates the DJANGO_SETTINGS_MODULE variable within Apache and makes it point to production.py. The PythonPath directive tells Apache in which directories to search for packages and files.

Posted in Web Development. Tagged with .

Topo for Kelmis Climbing Area

There is a tiny climbing area in an abandoned stone pit near Kelmis. It’s right around the corner from Aachen, where yours truly lives, so me and my fellow citizens can be found there sometimes. Unfortunately information regarding the climbs is rare. I managed to unearth a bare bones topo from the Internet Archive, which I’m publishing here for download. Judging from my own experience, the grading is sort of accurate, but the climbs at the outer left part of the main wall are missing. I’ve however heard that a guy from Belgium is working on documenting them as well.

Disclaimer: If have no idea where the topo originally came from and I take no responsibility for its correctness.

If you are the creator of the topo and want attribution of some sort (or if you want me to take down the link), please get in touch.

Posted in climbing. Tagged with , .

Wordpress

Wordpress Logo

This site is running on Wordpress now.

For a long time I had nursed my WP prejudices regarding code quality and style. Now that I have dug around in it quite a bit, I don’t feel particularly convinced that I was wrong. I think the perception of the Wordpress core developers regarding nice code is orthogonal to mine. Still I was able to come up with a script that imports posts from Tumblr (which I was using previously) and nicely integrates with the admin interface in less than an hour. I have submitted it for inclusion in the Wordpress core, but think I’ll have to find someone to rewrite it for PHP 4.

On the plus side, the administration interface is top-notch and the Carrington theme is totally impressive.