moeffju.net

Habari development

As you may or may not know, I’m now part of the core development committee of Habari. Habari is a next generation blogging platform written in object-oriented PHP using the model view controller design pattern. There, enough buzzwords?

Not having to support a huge installed codebase with a lot of legacy, we have a chance to “do things right” with Habari. Using MVC is certainly a good start, as is using PDO (now programming SQL injections takes effort). But the nicest codebase still doesn’t make a good product …

… which is why I’m asking you all:

  • What does a blogging platform absolutely need to do for you?
  • What would be really useful features to you?
  • How are you, personally, using your current platform?

Please feel free to write lengthy comments, send me mail, etc.

We are currently aiming for a developers preview release at the end of month, but there’s still a lot of work left to do. If you’re interested, have a look at the mailing lists, or just drop by on IRC, in #Habari on irc.freenode.net.

Habari

Habari is a new blogging platform being developed by a number of well known people, some of which are fed up with open source, others just looking for new challenges.

The thing about Habari is that is starts from scratch, and today. That means it doesn’t have to worry about a lot of existing legacy code and thus, downward compatibility. It is also being designed from the grounds up, using the latest available technology. Heck, it’s full OOP! It abstracts database access! You can plug in different theme engines (and, of course, there are plugins). In short, it could easily be the greatest thing since pressed words.

I wrote my first patches against Habari trunk today, one fixing a locale bug and making basic i18n work, the other mostly style changes. How could I resist joining the development frenzy!

Find me in the habari-dev group and on the Habari IRC channel, #habari on irc.freenode.net.

Reader Bar 0.21

Reader Bar marks the previous scroll position (the screen area visible prior to scrolling, to be exact). It helps to keep track of your reading position, especially when scrolling at the very bottom or very top of a page, when scroll steps are not integral.

Available in userscript and bookmarklet flavours. Tested with Firefox and Firefox w/ Greasemonkey.

Changes from 0.2 to 0.21: Added z-index to the marker element, to make it work right on sites like Wikipedia.

Update Jan 10th: The marker currently blocks clicks in a part of the page. This will be fixed shortly.

WordPress 2.1-alpha3 and Ultimate Tag Warrior

If you’re running WordPress 2.1 trunk from SVN (currently at 2.1-alpha3, r4663) with Ultimate Tag Warrior (UTW) 3.141592 (the latest version as of today), UTW will lose all tags on a post when a new comment is made.

To fix this, edit the ultimate-tag-warrior-actions*.php files (in your UTW directory, there should be one -actions.php and one -actions-wordpress2.php, simply edit both). In the function ultimate_save_tags($postID), add the following lines right after the opening curly bracket:

    if (!is_admin()) return $postID;
    if (!isset($_POST['tagset'])) return $postID;

Save the files and you should be all set.

The problem occurs because WordPress trunk calls the edit_post hook when new comments are added. UTW doesn’t check the environment and just assumes the admin wanted to delete all tags, and then dutifully removes the tags from the post.

The fix just does nothing when the edit_post hook gets called from outside the admin publish area.

Update: See also Thomas’ comment for the latest UTW version.

StudiVZ: Ids und Dumps

Ich hatte es ja schon angedeutet: Die User-, Album- und Foto-IDs beim StudiVZ sind far from unique. Ich hatte in den Tagen vor dem Blogpost ein bisschen mit den Ids rumgespielt, und sie natürlich auch in ihre binäre Repräsentation umgewandelt, einfach weil es nahe lag. Leider habe ich mir nicht so viel Mühe gemacht wie andere Leute; ich habe aufgehört, nachdem ich festgestellt habe, dass die ersten paar Bits scheinbar recht egal sind.

Jetzt weiß wohl jeder weshalb.

Mein Offset ist übrigens 23.

Und zum Datenbank-Dump nur so viel.

Nachtrag: Jetzt gibt’s €256 pro Bug, was wegen mehrerer Gründe lächerlich ist. Udo findet es jedoch - aus anderen Gründen - interessant.

StudiVZ: "Erfolg" ist Definitionssache

“studiVZ hat heute um 12 Uhr einen Phishing-Angriff bemerkt und erfolgreich abgewehrt” - wobei “erfolgreich abgewehrt” bedeutet, dass man erst mal alles runtergefahren hat und dann für knapp acht Stunden down war. Der “Phishing-Angriff” (eigentlich ein XSS-Wurm, aber wer wird sich denn mit Details aufhalten wollen) hatte in der Zwischenzeit schon ordentliche Kreise gezogen und Unmengen von Benutzerdaten (Login und Passwort) ausgespäht. Kommt halt alles darauf an, wie man “Erfolg” definiert…

Wer könnte auch ahnen, dass man Benutzereingaben im ‘Web 2.0’ irgendwie filtern müsste.

StudiVZ in den Medien (Privatsphäre für Anfänger)

Jaja, die Leute schreiben immer noch übers StudiVZ. Also schreib ich jetzt endlich mal die Sachen auf, die ich in den letzten Monaten (seit meiner Anmeldung beim StudiVZ, Mitte September) so bemerkt habe.

Das mit den Bilder-URLs ist ja schon stadtbekannt. Natürlich machen alle anderen Großen - wie Xing, flickr, etc. - auch so, und das macht es nicht viel besser, aber das ist ja kein Grund, nicht darüber zu schreiben. Man kann also auf Bilder immer zugreifen, wenn man eine direkte URL hat. Na gut.

Viel interessanter fand ich: Die User-IDs sind nicht unique. Man kann die ersten 8-24 Bits (je nach Länge der ID) recht frei ändern und landet immer noch auf dem selben Profil. Das selbe gilt für die Album-IDs und vermutlich auch für die Bild-IDs. Na, was das wohl für ein Algorithmus ist… *hust*

Jedenfalls kann man so sehr leicht alle Benutzer, Alben und Bilder enumerieren, indem man der showalbum.php beliebige IDs in relativ großen Schrittweiten gibt. Wenn man einen Treffer hat, steht die ‘wahre’, primäre Album-ID (sowie Titel und Besitzer) im Seitenquelltext. Damit kann man dann den Bildserver behämmern. Für nicht-öffentliche Alben muss man dann nur den Rest des Suchraums durchgehen, oder man knackt einfach die ID-Erzeugung. Der Bilderserver geht jetzt schon merklich in die Knie.

Listen aller Alben eines Benutzers gibt’s bei showpeoplealbums.php, wobei auch hier gilt: etwa die Hälfte der ID ist eh wurscht. Es gibt verschiedene Meldungen für “Album ist noch leer” und “hat keine Alben”.

Immerhin hat man durch die eigenen IDs (3-6 Zeichen) gegenüber UUIDs (16-36 Zeichen) Traffic gespart…

Auch interessant: Das StudiVZ benutzt offenbar Smarty und sajax. Smarty, klar, sinnvoll. Sajax, auch sinnvoll, aber hoffentlich haben sie nicht zu viele Funktionen exportiert, auf die Normalsterbliche eigentlich gar nicht zugreifen können sollten. Na, wer will’s testen?

Was haben wir noch … ach ja, das mit den nichtöffentlichen Profilen? Geht ja auch grade durch die Welt… sei es nun friends.php oder profile_guestbook_large.php oder showpeoplealbums.php, man kann sich so ziemlich alle Teile eines “privaten” Profils ansehen. Hübsch. Da fällt auch das “Diese Nachricht wurde von Foobar gelöscht und wird anderen Mitgliedern nicht mehr angezeigt” nicht mehr ins Gewicht.

Hätte ich mich doch nur noch ein paar Wochen länger geweigert, da mitzumachen! Le seufz! Todo für morgen: Profile meiner Freunde scrapen, mein Profil löschen, Freunde per ICQ anhauen, done. Gute Nacht.

Getting rid of the 'www' prefix

[lang_de]Dieser Eintrag ist nur auf Englisch verfügbar.[/lang_de]

You may or may not have heard about the no-www movement. All my sites have always been reachable with and without the www prefix, and I personally never use the www prefix if I can avoid it. I won’t get into the details of why it is a bad idea, but consider this: no one calls the web ‘WWW’ anymore, and this ‘abbreviation’ is a lot longer than the expansion (‘double-you double-you double-you’ vs ‘world wide web’). If anything, the prefix should be ‘web’.

Starting today, I’m having all my domains permanently redirect to the non-www version of the hostname.

Here’s a simple mod_rewrite recipe that should work for any domain:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L,NS]

Put it inside a <Location "/"> block in the appropriate VirtualHost block, or inside a .htaccess in the document root of your site (it doesn’t seem to work in a VirtualHost block in the server config, any ideas why?).

It’s like magic.

IP to country: ip2countryd using hostip.info data

[lang_de]Dieser Eintrag ist nur auf Englisch verfügbar.[/lang_de]

hostip.info is a free GeoIP service. Unfortunately their webservice is slow and they are in the middle of a backend change (from 256 ip_X tables to one table listing all /24 nets…). However, their information is more exact than that of countries.nerd.dk.

To convert the data from hostip.info’s format into something remotely sane usable, you have to merge the ranges into CIDR-blocks per country. If you don’t do that, you’ll get a 160MiB result file which will take ages for ip2countryd to process. With proper optimization and merging, though, the resulting file is barely 4MiB in size and ip2countryd loads like a breeze.

  • ip2countryd-r3.tgz 12KiB
    Revision 3 of ip2countryd, minor changes, includes a script to convert hostip.info CSV dumps to rbldnsd format.
  • hostip-data.tgz 1.1MiB
    The current dump from hostip.info in rbldnsd format, including the cached version.

The test service at udp://ubermutant.net:8000/ has been updated to r3 with the hostip.info db.

Now, for the rant. hostip.info used to use 256 tables in their DB - one for each class A network. Inside each of these tables were two columns for the second and third octet of the IP. Luckily, they got better and away from this inane structure, switching instead to one table that holds the IP in a single INT column, as a long. But they still store one record for each /24 subnet in existence, plus some invalid and reserved ones (0.0.0.0/24? righto!). I don’t know how they query this monster, since the new site source is not yet available in their SVN, but I’m not sure if I even want to know. The sanest possibility I can think of right now is to take the lower 24 bits of the query and look that up. That still leaves one question, though: Why, oh why, must this be done in gigantic MySQL tables and for every single class C subnet?

Sometimes, a database just isn’t the best solution.

IP to country

[lang_de]Dieser Eintrag ist nur auf Englisch verfügbar.[/lang_de]

If you need to find out what country an IP is in, but are forced to use PHP or some other language without proper DNS querying features (but which can do UDP), here’s a little something for you.

ip2countryd-r2.tgz 344KiB - ip2countryd revision 2
Includes the required data file (~2MiB) and the cached data (~432KiB).

Runs a daemon on UDP port 8000 (by default) that responds to an input IP address with the ISO country code of the IP’s country, or ‘error’ if anything goes wrong (no mapping, not an IP, etc.). There is a test server at udp://ubermutant.net:8000/.

$ nc -u ubermutant.net 8000
207.13.77.53
us
212.227.57.11
eu

Idea from WP-ShortStat and the associated ip2country service. I wrote this just for the fun of it and because I wanted to see how long it would take me.

Total time required: ~1 hour.