29 Aug 2013, 12:37

Deploying Perl Web-Apps with Puppet

Since I was asked for I’d like to show one way of how you can deploy your perl web apps using debian packages and puppet.

This post assumes that you want to install some Plack webapps, e.g. App::Standby, Monitoring::Spooler and Zabbix::Reporter.

Those are pretty straight-forward Plack Apps built using Dist::Zilla.

cd Monitoring-Spooler
dzil build
I’ve built debian packages of these CPAN modules. Using dh-make-perl this is reasonably easy, although you’ll need some switches to make dh-make-perl a little less picky:
dh-make-perl –vcs rcs –source-format “3.0 (native)” Monitoring-Spooler-0.04
After building and uploading these packages to my repository I continue to use Puppet to install and configure those.

For each of these packages there is a custom puppet module, e.g. app_standby for managing App::Standby. This module create all necessary directories, manages the configuration and installs the package from my repository. It does not, however, set up any kind of webserver or runtime wrapper. This is done by another module: starman.

For running my Plack apps I use Starman which is managed by it’s own puppet module. It will install the starman package, manage it’s config and create an apache config. The interesting part is that I use puppet to automatically create an apache config and a simple Plack/PSGI multiplexer app that allows me to handle requests to all three (or more) of these apps using a single starman instance.

If these apps were rather busy I’d use a separate starman instance for each one, but as it is I’m more than happy to avoid the overhead of running multiple starman instances.

My starman module is invoked from one of my service classes like this:

  class { ‘starman’:
    configure => {
      mounts    => {
        ‘zreporter’     => ‘/usr/bin/zreporter-web.psgi’,
        ‘monspooler’    => ‘/usr/bin/mon-spooler.psgi’,
        ‘monapi’        => ‘/usr/bin/mon-spooler-api.psgi’,
        ‘standby’       => ‘/usr/bin/standby-mgm.psgi’,
The starman module itself is pretty straight-forward, but below are the templates for the apache config and the PSGI multiplexer.


<IfModule mod_proxy.c>
<% if @configure.has_key?(“mounts”) -%>
<% @configure[“mounts”].keys.sort.each do |mount| -%>
   <Location /<%= mount %>>
      Allow from all
      ProxyPass           http://localhost:<%= @configure.has_key?(‘starman_port’) ? @configure[“starman_port”] : ‘5001’ %>/<%= mount %>
      ProxyPassReverse    http://localhost:<%= @configure.has_key?(‘starman_port’) ? @configure[“starman_port”] : ‘5001’ %>/<%= mount %>
<% end -%>
<% end -%>
use strict;
use warnings;

use Plack::Util; use Plack::Builder;

my $app = builder { <% if @configure.has_key?(“mounts”) -%> <% @configure[“mounts”].keys.sort.each do |mount| -%>    mount ‘/<%= mount %>‘  => Plack::Util::load_psgi(’<%= @configure[“mounts”][mount] %>’); <% end -%> <% end -%>    mount ‘/‘           => builder {         enable ‘Plack::Middleware::Static’, path => qr#/.+#, root => ‘/var/www’;         my $app = sub { return [ 302, [‘Location’,‘/index.html’], [] ]; };         $app;    } };


08 Oct 2012, 18:44

git: Rebase vs. Rebase

For a some time I’ve wondered about git rebase. At some point in the past I’ve realised that there is not one use in git rebase but (at least) two distict ones.

  • On the one hand git rebase is used to rebase a branch onto an updated source branch (source like in origin, not in source code).
  • On the other hand it’s used to rewrite commit history.

What’s rebase?

A rebase makes git rewind your commit history up to a certain point and than re-apply your patches onto another starting point. The starting point depends on the exact type of rebase you do and what you tell git.

Rebase a branch

Why would you want to rebase a branch onto another one and what does it do?

If you have a feature branch and want this to be merged with your master branch you could of course merge it. If you do so and your feature branch is not based of the last commit in master git will create a new merge commit since it has to merge two branches of a tree. If you’d rebase your feature branch onto the tip of master you’d have a linear merge history w/o a merge commit instead.

Rewrite a branch

Why would you want to rewrite your commit history? What if you make mistakes while crafting a new branch? If you’re following common VCS advice you’ll probably commit often. Probably between some mistake you’ve made and the time you did correct it.

Now you’d have your shiny new feature commit and two or more commits w/ bugfixes to your initial commit in this feature branch. Some people prefer to keep the history of their mistakes. Those could just merge this new feature branch into their master branch.

Others prefer to keep their commit history clean (you wouldn’t release a book which includes all mistakes and corrections you’ve made, would you?). Here comes git rebase -i to the rescue. This rebases the current branch onto itself. This may sound a bit silly but it allows you to drop commits or more importantly to combine (squash) commits together!

Where to got from here?

This post wasn’t meant to give a complete introduction to git rebasing. There are plenty of great tutorials out there. I did just want to highlight some points which were important to me.

02 May 2012, 13:20

Stop writing useless programs


It’s kinda rude, but they aren’t entirely wrong …

13 Apr 2012, 08:00

PHP is broken

PHP: a fractal of bad design via Fefe.

02 Oct 2011, 16:13

VBoxAdm 0.1.15

I’ve just uploaded VBoxAdm 0.1.15. It includes another set of major refactorings. Please be careful when upgrading and watch your logfiles closely for any errors that may occur. Especially the Vacation module was refactored.

The time when the project will leave it’s alpha stage is drawing closer. VBoxAdm is now running on several largish sites under my direct administrative control, so I’ve got plenty of possiblities for some real-world testing. Several other migrations/installations are planned for the near future. Once it has proven sufficiently stable on these mailservers I’ll announce the the end of the alpha phase and enter beta testing.

Stay tuned!

10 Jul 2011, 16:57

GIT: Rewriting commit history - change author and email

Quicklink: How to change author and email in the whole commit History: http://theelitist.net/git-change-revision-author/

16 Apr 2011, 13:14

VBoxAdm: Mailinglist and API

A short status update regarding VBoxAdm.


Finally I’ve created a Mailinglist: http://www.vboxadm.net/support.html#mailinglist


I’ve been refactoring the Code for a while to turn it more into a MVC-Shape. This means separating the Model from the Controller (former VBoxAdm::Frontend, now VBoxAdm::Controller::Frontend). The ultimate goal of this work is to support code reuse and support for multiple ways to manipulate the data. Once the Model classes are stable I’ll finish the command line interface as well as the HTTP-API. This will provide three ways to modify the underlying data:
  • Web Frontend
  • HTTP-API (no REST for now, maybe later)
  • CLI
The Mailarchive is postponed for the time being.

Auto Configuration

Most Mailclients, like Outlook, Thunderbird and KMail, support a way of client auto-configuration. When setting up a new mail account they request a certain URL derived from the mail address and if they find an XML document with the expected information there they’ll use this information to set the correct username, mailserver and protocols. Support for this was added recently. There is even support for the weird way MS Outlook does this. However Outlook support is, so far, based solely on the documentation on Technet. Due to the lack of a Outlook license I wasn’t able to test it. Please provide feedback.

Future Work

After the refactoring, API and CLI are finished I’m going to look into the Mailarchive again. After that I’ll look into Quota Support, Mailman integration and I’d like to find a way to get the Postfix Logs into the database to ease support work. Having the Log in the database in a parsed format - no raw syslog to db - would make support request more easy to handle. No more need to log into the server and grep through the mail.log.

Further feature request are always welcome. Please direct any ideas and comments to the mailinglist at vboxadm@vboxadm.net.

19 Dec 2010, 17:38

Handling salted passwords in Perl

While working on VBoxAdm I’ve came to a point where I did want to support salted passwords. Salted passwords however are a bit difficult since you need to extract the salt from the existing password hash and compare it to the user supplied password to hash it and compare the result. You can’t simply hash the supplied pass and use a random salt, that would produce different hashes.

If you’re not into salted hashes, I’ll try to explain how salted hashes are generated, why they are and how you can handle them.

What are salted hashes and why do you need them?

The simplest way to store passwords in a database would be to use plaintext. Let’s assume for the remainder of this post that we’ll use the password ‘password’ and the salt ‘salt’. If you use plaintext you just store the string ‘password’ in your database. That is easy to implement since you don’t need to do anything with the password and this gives you much flexibility since you can do anything with the password, e.g. support challenge response authentication schemes. However this has a major drawback: The (database) administrator and perhaps others, as well as any intruders that gain access to your database can see all users passwords. In a perfect world this wouldn’t be a big problem since all users should use a unique password for every service they use. Yet in the real world there is small but important problem: Many users will re-use their passwords for other services. This would allow an intruder to abuse the passwords to access (maybe) much more important accounts of your users and cause much trouble to them and possibly bad PR to you.

It’d be much better if the passwords would be encrypted in some way so the cleartext is not directly visible from the database. This would help with security and give your users more privacy. At least I would not want that anybody knows what passwords I use. Not even the administrator of the site I use the password for. This is were hashing comes into play. Hashes are cryptographic one-way functions that have the ability to produce an (almost) unique output for a given input. The same input always produces and same output and it is a very rare occasion that two different inputs produce the same output (which would be called a collision).  This solves much of the initial problem, but still some issues remains: If two users use the same password this would be immediately visible because they would have the same hashes. Another issue is that you can easily lookup the cleartext for a given hash in a rainbow table. I’m sure that at least intelligence services will have huge rainbow tables.

Luckily someone came up with the idea of salted hashes. A salted hash is generated by creating a random salt for every hashing operation and appending this salt onto the cleartext. Since there must be a way to compare hashes later the salt is usually appended to the resulting hash and can be extracted from there for subsequent hashing and comparison. This makes salted hashes pretty much safe against a wide area of attacks and meets many privacy requirements.

How to deal with these salted hashes in perl?

I’ll use the salted hashes created by Dovecots dovecotpw utility as an example since these were the hashes of my concern and they aren’t to most simple ones. These hashes are created by generating a random salt, appending it to the cleartext and appending the salt to the hash.
SSHA(password, salt) = SHA(password, salt) + salt
The SHA1 hash uses 20 bytes of (binary) data for the hash. The salt is variable length and consists of binary data. This is important: The salt is not just ASCII (7-bit) or UTF-8 (variable lenght, limited value range) but uses the full eight bit of each byte to allow for maximum entropy. This is important. If you doubt it get a good book on cryptograhpy and read up on the issue of randomness, entropy and cryptanalysis. The problem here is that perl is tailored to deal with text data and numbers but not binary data. I C this would be an easy task, but perl needs special care to handle this requirements.

Generating an salted hash is pretty easy: Generate a number of valid byte values (0-254) and pack() it into a binary string, e.g.:

sub make_salt {
    my $len   = 8 + int( rand(8) );
    my @bytes = ();
    for my $i ( 1 .. $len ) {
        push( @bytes, rand(255) );
    return pack( ‘C*‘, @bytes );
However if you want to compare a user-supplied pass with the salted hash in your database you have to take some more steps. You’ll first need to retreive the old salted hash from the database, extract the salt and hash the user supplied password toegether with this salt. If you’d use another salt the resulting hashes would be different and the user would not be able to login although the passwords match.

In my implementation I did separate the code into a split_pass method that dissects the old hash and extracts the salt (and possibly the password scheme used) and a make_pass method that takes a cleartext, a password scheme and a salt to generate a hashed password. The resulting hash is them compared with the stored hash and if they match the user may login or do whatever the authorization was requested for.

The split_pass method basically strips of the password scheme stored in front of the hash between curly brackets, decodes the Base64 encoded hash, unpack()s it and packs everything after the hash again into a binary string using pack(‘C*‘,@salt). The pack() template represents a one byte char, which is what we need here.

For the actual implementation I suggest you look at the Perl Module VBoxAdm::DovecotPW distributed with VBoxAdm.

package VBoxAdm::DovecotPW;

use strict;
use warnings;

use MIME::Base64;
use Digest::MD5;
use Digest::SHA;


my %hashlen = (
    'smd5'    => 16,
    'ssha'    => 20,
    'ssha256' => 32,
    'ssha512' => 64,

# Usage      : my $hash = VBoxAdm::DovecotPW::plain_md5('pwclear');
# Purpose    : ????
# Returns    : ????
# Parameters : ????
# Throws     : no exceptions
# Comments   : none
# See Also   : http://wiki.dovecot.org/Authentication/PasswordSchemes
sub plain_md5 {
    my $pw = shift;
    return "{PLAIN-MD5}" . Digest::MD5::md5_hex($pw);

sub ldap_md5 {
    my $pw = shift;
    return "{LDAP-MD5}" . pad_base64( Digest::MD5::md5_base64($pw) );

sub smd5 {
    my $pw = shift;
    my $salt = shift || &make_salt();
    return "{SMD5}" . pad_base64( MIME::Base64::encode( Digest::MD5::md5( $pw . $salt ) . $salt, '' ) );

sub sha {
    my $pw = shift;
    return "{SHA}" . MIME::Base64::encode( Digest::SHA::sha1($pw), '' );

sub ssha {
    my $pw = shift;
    my $salt = shift || &make_salt();
    return "{SSHA}" . MIME::Base64::encode( Digest::SHA::sha1( $pw . $salt ) . $salt, '' );

sub sha256 {
    my $pw = shift;
    return "{SHA256}" . MIME::Base64::encode( Digest::SHA::sha256($pw), '' );

sub ssha256 {
    my $pw = shift;
    my $salt = shift || &make_salt();
    return "{SSHA256}" . MIME::Base64::encode( Digest::SHA::sha256( $pw . $salt ) . $salt, '' );

sub sha512 {
    my $pw = shift;
    return "{SHA512}" . MIME::Base64::encode( Digest::SHA::sha512($pw), '' );

sub ssha512 {
    my $pw = shift;
    my $salt = shift || &make_salt();
    return "{SSHA512}" . MIME::Base64::encode( Digest::SHA::sha512( $pw . $salt ) . $salt, '' );

sub make_pass {
    my $pw     = shift;
    my $scheme = shift;
    my $salt   = shift || &make_salt();
    if ( $scheme eq 'ldap_md5' ) {
        return &ldap_md5($pw);
    elsif ( $scheme eq 'plain_md5' ) {
        return &plain_md5($pw);
    elsif ( $scheme eq 'sha' ) {
        return &sha($pw);
    elsif ( $scheme eq 'sha256' ) {
        return &sha256($pw);
    elsif ( $scheme eq 'sha512' ) {
        return &sha512($pw);
    elsif ( $scheme eq 'smd5' ) {
        return &smd5( $pw, $salt );
    elsif ( $scheme eq 'ssha' ) {
        return &ssha( $pw, $salt );
    elsif ( $scheme eq 'ssha256' ) {
        return &ssha256( $pw, $salt );
    elsif ( $scheme eq 'ssha512' ) {
        return &ssha512( $pw, $salt );
    else {
        return "{CLEARTEXT}" . $pw;

sub make_salt {
    my $len   = 8 + int( rand(8) );
    my @bytes = ();
    for my $i ( 1 .. $len ) {
        push( @bytes, rand(255) );
    return pack( 'C*', @bytes );
# this method was copied from some module on CPAN, I just don't remember which one right now
sub pad_base64 {
    my $b64_digest = shift;
    while ( length($b64_digest) % 4 ) {
        $b64_digest .= '=';
    return $b64_digest;

sub verify_pass {

    # cleartext password
    my $pass = shift;

    # hashed pw from db
    my $pwentry = shift;

    my ( $pwscheme, undef, $salt ) = &split_pass($pwentry);

    my $passh = &make_pass( $pass, $pwscheme, $salt );

    if ( $pwentry eq $passh ) {
        return 1;
    else {

sub split_pass {
    my $pw       = shift;
    my $pwscheme = 'cleartext';

    # get use password scheme and remove leading block
    if ( $pw =~ s/^\{([^}]+)\}// ) {
        $pwscheme = lc($1);

        # turn - into _ so we can feed pwscheme to make_pass
        $pwscheme =~ s/-/_/g;

    # We have 3 major cases:
    # 1 - cleartext pw, return pw and empty salt
    # 2 - hashed pw, no salt
    # 3 - hashed pw with salt
    if ( !$pwscheme || $pwscheme eq 'cleartext' || $pwscheme eq 'plain' ) {
        return ( 'cleartext', $pw, '' );
    elsif ( $pwscheme =~ m/^(plain-md5|ldap-md5|md5|sha|sha256|sha512)$/i ) {
        $pw = MIME::Base64::decode($pw);
        return ( $pwscheme, $pw, '' );
    elsif ( $pwscheme =~ m/^(smd5|ssha|ssha256|ssha512)/ ) {

        # now get hashed pass and salt
        # hashlen can be computed by doing
        # $hashlen = length(Digest::*::digest('string'));
        my $hashlen = $hashlen{$pwscheme};

        # pwscheme could also specify an encoding
        # like hex or base64, but right now we assume its b64
        $pw = MIME::Base64::decode($pw);

        # unpack byte-by-byte, the hash uses the full eight bit of each byte,
        # the salt may do so, too.
        my @tmp  = unpack( 'C*', $pw );
        my $i    = 0;
        my @hash = ();

        # the salted hash has the form: $saltedhash.$salt,
        # so the first bytes (# $hashlen) are the hash, the rest
        # is the variable length salt
        while ( $i < $hashlen ) {
            push( @hash, shift(@tmp) );

        # as I've said: the rest is the salt
        my @salt = ();
        foreach my $ele (@tmp) {
            push( @salt, $ele );

        # pack it again, byte-by-byte
        my $pw   = pack( 'C' . $hashlen, @hash );
        my $salt = pack( 'C*',           @salt );

        return ( $pwscheme, $pw, $salt );
    else {

        # unknown pw scheme


18 Apr 2009, 08:00

reStructured Text

I’ve discovered reStructured Text some time ago and have been using it since then for several tutorials, like the ISP Mailserver or the Rootserver ones.


I’d suggest to have a look at those if LaTeX would be too much of an overkill.

14 Jan 2009, 14:33


Today Qt Software made an very important announcement: They are going to release Qt 4.5 with an additional license option: the LGPL. This means that Qt can be used in closed-source-software (and more restrictive OSS licenses) without paying royalties to Qt Software. This is great news. I hope that now there will be a SWT-Qt binding for eclipse which could improve the speed and responsiveness of eclipse by an order of magnitude (if it’s done right).

This is very, very promising.

26 Nov 2008, 21:30

Auto-generate toString() in Eclipse

Ever wondered why Eclipse provides generators for hashCode() and equals() but not for toString()? I don’t know why, but there is a very handy plugin which will relieve you from this task: JUtils toString.

10 Jun 2008, 14:42

Keyword Substitution bei SubVersion

Bei SVN gibt es, wie bei CVS, die Möglichkeit bestimmte Schlüsselwörter in Textdateien automatisch ersetzen zu lassen. Dies sind unter anderem die praktischen Schlüsselwörter $Revision$ für die aktuelle Revisionsnummer der Datei, $Author$ für den Autor sowie $Date$ für das letzte Modifikationsdatum. Dieses Variablen werden immer bei einchecken auf den neusten Stand gebracht. Damit man dieses Feature jedoch nutzen kann muss man es erst über “svn propset svn:keywords “Revision Date Author” filename.ext” aktivieren.

Mehr Informationen im SVN Buch.

09 Jun 2008, 22:29

Eclipse unter Linux x64

Nach der Migration meines Systems von 32-bit auf einen 64-bit Kernel kam es beim Starten von Eclipse zu einer komischen Fehlermeldung:

libgtk2.0-0: error while loading shared libraries: libgtk-x11-2.0.so.0
Der Grund war einfach, dass ich eine 32-bit Version von Eclipse (SWT) hatte und die natürlich die entsprechenden Libraries nicht gefunden hat. Die Lösung habe ich in einem Debian Bugreport gefunden.

30 Apr 2008, 22:10

Doppelte Einträge im Eclipse Content-Assist

In meiner Eclipse Installation (3.3) unter Linux habe ich seit einiger Zeit das Problem gehabt, dass die Einträge im Content-Assist bzw. der Code-Completion alle doppelt aufgetaucht sind.

Eclipse Content-Assist showing double entries

Der Grund darin lag bei Mylin, das sich bei der Installation irgendwie in die Suggestions eingeklinkt hat.

Eclipse Content-Assist showing each entry only once!

Correcting Eclipse Content-Assist settings

18 Feb 2008, 17:24


python + contracts + besseres exception handling + .net/mono anbindung” -> http://cobra-language.com/

08 Feb 2008, 06:00

SVN Repository verschieben

Wer kennt das nicht ™? Da will man mal eben die Domain des SVN Repositorys ändern.

Aber wie sage ich den Arbeitskopien, dass das Repository umgezogen ist?

Dafür gibts zum Glück den “svn switch –relocate” Befehl.

Einfach auf der Befehlszeile

svn switch –relocate alteURL neueURL
aufrufen und schon sind alle entsprechenden Repositorys umgezogen.

In Eclipse gehts ganz einfach über die “SVN Repository Exploring” Perspektive mit dem Befehl “Relocate” im Kontextmenü.

SVN Switch Relocate Eclipse

04 Feb 2008, 06:00

RCP Tutorial

Eine gute Einführung in Eclipse/RCP Programmierung gibts bei vogella.de

28 Jan 2008, 17:41

PHP5.2 bringt inkonsistente include_path Fehler

Es sieht ganz so aus als ob PHP5.2.x einen komischen Bug in Verbindung mit Apache VHosts und dort gesetzten include_paths hat.

Sobald man in einem VHost den include_path ändert funktioniert ini_set in allen Vhosts nicht mehr. Um das ganze noch ein wenig spannender zu machen tritt der Bug nicht immer auf, d.h. er ist extrem schwer zu debuggen.


Update: Die Lösung war keine Include_Paths in den Vhosts zu setzen, da das PHP5 Modul damit Probleme hat.

22 Jan 2008, 10:49

Email Adresse in PHP validieren

if(!pregmatch(“/^[A-Z0-9.%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}$/i”,$email)) { return true; }

Quelle: How to find or validate Email Adress 

13 Dec 2007, 11:47

Eclipse RCP: CorruptedCodeException

Wenn man versucht eine RCP Application mit dem FlexiProvider und dem FhG Codec zu bauen laufen einem zuweilen schon sehr komische Fehler über den Weg.

Interessant wird es wenn die RCP-App. gar nicht mehr startet und CorruptedCodeExecptions schmeißt.

Es gibt ein paar Punkte auf die man achten sollte.

RCP Manifest - Build Screen

In der Build Configuration muss das aktuelle Verzeichnis (.) aufgenommen werden.

RCP Manifest - Dependency Screen

Man sollte, wenn möglich, auf unnötige Plug-ins verzichten.

RCP Manifest - Runtime Screen

Gaaanz wichtig: Alle Pakete das Projekts exportieren und, noch wichtiger, das Verzeichnis “bin/” mit in den Classpath!

Good Luck.

25 Nov 2007, 23:33

Europa ohne VE, Callisto mit?

Na toll, das neuste Eclipse Release, Europa, kommt ohne Visual Editor Unterstützung, nur die Vorversion, Callisto, wird unterstüzt. Das ist irgendwie doof …

22 Nov 2007, 05:30

WordNet mit JWNL

Wer auf WordNet mit Java zugreifen will, der stößt über kurz oder lang auf die freie Bibliothek JWNL - Java WordNet Library. Wenn man allerdings versucht diese mit einer aktuellen Version WordNet zu nutzen schmeißt sie nur mit komischen Fehlermeldungen um sich - selbst wenn man den Pfad zur Datenbank in der Konfigurationsdatei richtig angegeben hat.

Das Problem dabei ist, dass JWNL nur mit WordNet 2.0 für Windows zusammenarbeiten will - was freundlicherweise nirgends (deutlich) erwähnt wird.

Kurzanleitung für den Einsatz von WordNet unter Java:

  • WordNet runterladen und installieren (nur Windows)
  • JWNL runterladen, die Klassen (commons-logging,jwnl und utilities) in den Build-Path einbinden
  • In der Datei file_properties.xml den Pfad auf das Unterverzeichnis dict der WordNet Installation verweisen lassen.
  • Mit JWNL.initialize(new FileInputStream(“path/to/file_properties.xml”) und Dicitornary wordnet = Diricotnary.getInstance() eine neune Insatnz von Wordnet bzw. JWNL erzeugen.
  • Danach kann man mit wordnet.lookupAllIndexWords(String) auf die Wordnet Datenbank zugreifen.
Hier eine Beispielklasse die die wichtigsten Wordnet API-Calls demonstriert:

package utils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import net.didion.jwnl.JWNLException;
import net.didion.jwnl.data.IndexWord;
import net.didion.jwnl.data.IndexWordSet;
import net.didion.jwnl.data.PointerUtils;
import net.didion.jwnl.data.Synset;
import net.didion.jwnl.data.list.PointerTargetNode;
import net.didion.jwnl.data.list.PointerTargetNodeList;
import net.didion.jwnl.dictionary.Dictionary;

public class WordNetUtils {

private Dictionary wordnet = null;

public WordNetUtils() {
this.wordnet = Dictionary.getInstance();

public List<string> getSynonyms(String word) {
List</string><string> syns = new ArrayList</string><string>();
IndexWordSet iws;
try {
iws = wordnet.lookupAllIndexWords(word);
IndexWord[] words = iws.getIndexWordArray();
for (int i1 = 0; i1 &lt; words.length; i1++) {
} catch (JWNLException e) {
return syns;

private List<string> getAllSynonyms(IndexWord w) throws JWNLException {
List</string><string> syns = new ArrayList</string><string>();
Synset[] senses = w.getSenses();
for (int i = 0; i &lt; senses.length; i++) {
PointerTargetNodeList relatedList = PointerUtils.getInstance()

<pointertargetnode> it = relatedList.iterator();
while (it.hasNext()) {
PointerTargetNode elem = (PointerTargetNode) it.next();
Synset s = elem.getSynset();
for (int j = 0; j &lt; s.getWords().length; j++) {
relatedList = PointerUtils.getInstance().getDirectHypernyms(
it = relatedList.iterator();
while (it.hasNext()) {
PointerTargetNode elem = (PointerTargetNode) it.next();
Synset s = elem.getSynset();
for (int j = 0; j &lt; s.getWords().length; j++) {
relatedList = PointerUtils.getInstance().getDirectHyponyms(
it = relatedList.iterator();
while (it.hasNext()) {
PointerTargetNode elem = (PointerTargetNode) it.next();
Synset s = elem.getSynset();
for (int j = 0; j &lt; s.getWords().length; j++) {
return syns;
}</pointertargetnode>public List<string> getSynonyms(List</string><string> toks) {
List</string><string> retval = new ArrayList</string><string>();
for (int i = 0; i &lt; toks.size(); i++) {
return retval;
}</string>public Set<string> getSynonyms(Set</string><string> toks) {
Set</string><string> retval = new HashSet</string><string>();
for (Iterator</string><string> iterator = toks.iterator(); iterator.hasNext();) {
String name = (String) iterator.next();
return retval;

08 Nov 2007, 10:00

javax.swing.GroupLayout cannot be resolved

Problem: Ein Java Quelltext lässt sich nicht kompilieren, weil die IDE sich über den Fehler “javax.swing.GroupLayout cannot be resolved” beschwert.

Grund: GroupLayout ist erst in Java 6 verfügbar.

Lösung: Java 6 installieren und aktivieren :)

07 Nov 2007, 08:00

Ohloh - das Open-Source Netzwerk

Schon gewusst? Unter ohloh.net gibt es ein Open-Source Netzwerk das umfassende Statistiken zu verschiedenen Open-Source Projekten liefert. So ähnlich wie Freshmeat, nur mehr Web 2.0. Eigentlich ganz nett und recht informativ.

05 Nov 2007, 08:00

Vim als Entwicklungsumgebung

Wie kann man Vim als Entwicklungsumgebung nutzen? Lesen.

30 Oct 2007, 07:30

PHP/MySQL: Client does not support authentication protocol

Problem: PHP/MySQL kann sich nicht zu einem MySQL-Server verbinden und bricht mit der Fehlermeldung Client does not support authentication protocol ab.

Das passiert wenn die Version der MySQL Laufzeit Bibliothek inkompatibel mit der Version des MySQL-Servers ist, da irgendwann das Format der Passworte geändert wurde.

Wenn man sich dennoch mit einem “alten” Client zum Server verbinden will kann man für diese Benutzer das Passwort auf das alte Format zurücksetzen indem man folgenden Befehl ausführt SET PASSWORD FOR ‘some_user’@‘some_host’ = OLD_PASSWORD(‘newpwd’);.

Weitere Informationen gibts in der MySQL-Dokumentation.

28 Oct 2007, 07:30

Quellcode Listings in LaTeX

Wer Quellcode in LaTeX Dokumente einbetten möchte, der kann entweder einen Verbatim Block benutzen oder direkt ein Paket, welches dafür gedacht ist Quellcode anzuzeigen: Listings.

Um dieses Paket zu nutzen muss es zunächst im Header  mit folgendem Befehl eingebunden werden: %% listings \usepackage{listings} \lstset{numbers=left, numberstyle=\tiny, numbersep=5pt} \lstset{language=Perl} %% end listings

Später im Dokument hat man dann verschiedene Möglichkeiten die Funktionalität zu nutzen.

  • Entweder für einzelne Zeilen mit \lstinline|print “Hallo Welt!”|
  • Oder als eigener Block, ähnlich verbatim, mit \begin{lstlisting}caption=Diff\end{lstlisting}
  • Alternativ kann man auch eine externe Datei einbetten: \lstinputlisting[frame=single,label=Codebeispiel,caption=Ein Codebeispiel]{code.java}
Die Vorteile gegenüber Verbatim oder anderen Lösungen sind natürlich die Zeilnnummern, der optimierte Font und die teilw. vorhandene Syntax Unterstützung.

Fazit: Hilfreich :)

22 Oct 2007, 07:30

Komplexe Datenstrukturen in PHP?

Nachdem ich mir Gedanken über eine Portierung des Spell Checkers von Java nach PHP gemacht habe, ist mir aufgefallen, dass es scheinbar gar keine komplexen Datenstrukturen in PHP gibt.

Natürlich kann man sich das alles selbst bauen, aber eine ordentliche Implementierung von Set, List, Tree & Co. wie in Java scheint es in PHP nicht zu geben.

Das Problem bei der PHP Umsetzung ist im Moment, dass ich ja keine ständig laufende Application sondern einzelne Request habe und daher nicht jedesmal den langwierigen Trainingsprozess durchlaufen kann. Als Alterantive scheint mir eine SQL-Datenbank geeignet, aber bevor das so funktioniert wie ich es mir vorstelle muss ich noch einen Weg finden die Daten dort effektiv abzulegen und aufzufinden. 90.000 SQL-Abfragen pro Suchanfrage sind einfach noch ein bischen zu viel ;)

21 Oct 2007, 07:30

P2P Wiki in Java

Unter dem Namen jP2PWiki habe ich eine Beispielimplementierung eines P2P Wikis in Java veröffentlicht.

Das ganze ist nicht als stabile Software sondern eher als Proof-of-Concept anzusehen, aber möglicherweise hat der eine oder andere Interesse an dieser Thematik.

Alle weiteren Details finden sich auf der Projektseite.

20 Oct 2007, 08:00

No Spam!

Gestern bin ich durch eine Anzeige auf das Buch “No Spam! Besser vorbeugen als heilen” von Tobias Eggendorfer aufmerksam geworden.

In der Anzeige wurden unter andem die folgenden Punkt angeführt:

  • Woher haben Spammer die Adressen?
  • Grundlegende Vorsichtsmaßnahmen
  • eMail Adressen verstecken
  • Harvester blockieren
  • Absichern von Mailinglisten und Newslettern
Wenn ich das Inhaltsverzeichnis so lese, fage ich mich ernsthaft warum man dieses Thema auf ca. 160 Seiten aufblähen muss, und warum man dazu ein ganzes Buch verfasst. Die angesprochenen Punkt lassen sich eigentlich in ein paar Zeilen zusammenfassen, und genau das werde ich hier versuchen.

Was ist Spam?

Der Begriff Spam stammt aus einem Monty Python Sketch und ist die Umgangssprachliche Bezichnung für UCE/UCB was für “Unsolicited Commercial E-mail” bzw. “Unsolicited Commercial Bulk E-mail” steht. Gemeint sind damit unerwünschte Nachrichten die in großem Umfang an eine Vielzahl von Benutzern verschickt wird. Ein weiteres Merkmal von Spam ist, dass in der Regel keine (bewusste) Anmeldung/Einwilligung zum Empfang desselben erfolgte.

Woher haben Spammer die Adressen?

Wer eine möglichst große Anzahl an Personen im Internet erreichen will, kommt über kurz oder lang vielleicht auf die blöde Idee einfach Massenhaft Mails mit Werbung zu verschicken. Doch woher bekommt man die ganzen Adressen? Dafür gibt es ein paar Möglichkeiten. Der naivste Ansatz ist die Brute-Force Methode, d.h. einfach einen Mailserver kontaktieren und alle möglichen Kombinationen von zulässigen Zeichen als Emfänger auszuprobieren. Dies ist natürlich sehr Zeit- und Resourcen intensiv und führt wahrscheinlich bei den meisten Mailservern dazu, dass der sendende Host komplett ausgesperrt wird.

Ein besserer Ansatz, für den Spammer, ist es im Internet nach echten Adressen zu suchen. Dazu werden, ähnlich wie bei Suchmaschinen, sogenannte Spider bzw. Harvester eingesetzt, die von einer Seite aus starten und dann jedem ausgehnden Link folgen und alle Mail-Adressen, erkennbar an dem “mailto:” Prefix, in einer Datenbank speichern. Hier ist auch gleich der erste Ansatz den Spammern die Tour zu vermiesen: Die eigenen eMails verschleiern. Dazu gibt es mehrere Möglichkeiten, aber dazu später mehr.

Grundlegende Vorsichtsmaßnahmen

Hier lautet die oberste Devise: Datensparsamkeit. Man sollte generell möglichst sparsam mit seinen Daten, in diesem Fall der Mail-Adresse, umgehen. Wenn man jedoch seine Adresse seine eigene Adresse veröffentlichen muss, der sollte sicher Gedanken darüber machen wie er diese für Harvester unbrauchbar macht.

Dafür gibt es verschiedene Möglichkeiten:

  • eMail Adresse verschleiern/verstecken
  • einmal Adressen, d.h. eine Adresse pro Nutzungszweck
  • ablaufende Adressen
Auf die einzelnen Punkte gehe ich gleich nochmal ein.

eMail Adresse verstecken

Wenn man seine Adresse für Menschen zugänglich machen will, oder muss, Stichwort Impressumspflicht, dann sollte man diese entweder durch Ersetzungen unkenntlich machen, z.B. info@gauner.org wird zu into_AT_gauner_DOT_org, wobei es hier auch die Möglichkeit gibt, dass Spammer diese Ersetzungen einfach enttarnen können. Eine weiter Möglichkeit ist es die ganze Adresse, oder einen Teil davon, durch Grafiken zu ersetzen. Eine dritte Möglichkeit ist den “mailto:info@gauner.org” Teil durch eine Javascript Funktion zu ersetzen die beim anklicken die richtige Adresse erzeugt.

Einmal Adressen

Eine gute Möglichkeit die Menge des eingehenden Spams zu steuern und zu kontrollieren woher der Spam kommt ist das verwenden von sog. einmal Adressen. Hierbei legt man für jeden Verwendungszweck, z.B. Registrierung in einem Forum oder Blog, eine eigene Adresse wie z.B. gauner-blog@xy.host.tld an und leitet diese auf seine eigentliche Adresse weiter. Wenn man jetzt einmal Spam erhällt kann man anhand der Empfänger-Adresse einfach feststellen wie der Spammer an die Adresse gekommen ist. Jetzt kann man jederzeit diese Adresse zu löschen und man wird auf diesem Weg keinen Spam mehr erhalten. Der Nachteil hierbei ist, dass man eine ziemlich große Zahl an Weiterleitungen anlegen muss und einen Provider benötigt der dies unterstützt.

Ablaufende Adressen

Es ist auch möglich einfach Adressen zu verwenden aus denen deutlich wird, wann Sie ablaufen. Diese Adressen haben die form Max.Mustermann-expires20071031@gauner.org. Diese Adresse können dann nach belieben Benutzt werden, da man Sie nach einer gewissen Frist, meist wenige Monate, einfach nicht mehr benutzt. Ein Nachteil ist natürlich, dass man diese Adresse dann ggf. an vielen Stellen ändern muss. Mir persönlich wäre dieser Aufwand einfach zu groß.

Harvester blockieren

Um den Spammern das Leben weiterhin schwer zu machen gibt es sog. Honeypot Ansätze, die versuchen Harvester in eine Falle zu locken. Diese Falle ist eine speziell angelegte Webseite mit jeder Menge interner Verweise und künstlich erzeugten, ungültigen eMail-Adressen, die die Ressourcen der Harvester binden und mit unnützen Adressen überfluten soll.

Absichern von Mailinglisten und Newslettern

Zum absichern von Mailinglisten und Newslettern ist es generell sinnvoll entweder die vorhandenen Funktion zur Entfremdung der Mail-Adressen der Nutzer zu verwenden, oder sich selbst Gedanken über eine solche Funktion zu machen. Der, in meinen Augen, beste Ansatz ist die verwendung von Bilder zur Darstellung der Mail-Adressen, bzw. von Teilen davon. Dabei darf man natürlich nicht vergessen, dass der Inhalt der, im Bild dargestellten Zeichenkette, nicht im alt Tag angegen werden sollte. Dies läuft zwar der Barrierefreiheit entgegen, aber das ist wohl einer der Kompromisse die man im Moment eingehen muss.


Ich hoffe, dass ich hiermit einige vorbeugende Schritte zur Spam Vermeidung ein wenig erläutern konnte und falls noch Fragen auftauchen steht natürlich die Kommentar Funtkion jederzeit offen. Da man auch hier nicht von Spam verschont bleibt ist leider das lösen einer kleinen Rechenaufgabe notwendig. Aber zum Thema Kommentar-Spam werde ich ein anderes mal etwas sagen …

11 Oct 2007, 10:11

MySQL: Zufälligen Eintrag ausgeben

Kurztipp: Zufälligen Eintrag aus einer MySQL-Tabelle ausgeben

Möchte man mit MySQL einen zufälligen Eintrag aus einer Tabelle ausgeben, so hilft das folgende Statement: “ ORDER BY RAND(NOW()) LIMIT 1” am Ende der Query.

20 Sep 2007, 11:36

Codezeilen zählen

Kurztipp: Wie kann ich die Zeilen eines (Programmier-) Projektes zählen? (SLOC)

Das beste Tool für diesen Zweck dürfe CLOC sein, zumindest und Unix/Linux.

Ein anderer Weg ist eine Unix-Command Folge:find . -regex ‘.*.(c|h|cxx|cpp)’ -print0 | xargs -0 cat | wc -l

18 Sep 2007, 09:35

PHP: Cannot access empty property

Kurztipp: Probleme nach der Migration von PHP4 zu PHP5 (I)

Folgendes Problem tritt nach der Migration von PHP4 zu PHP5 auf:

Fatal error: Cannot access empty property in /www/xyz/abc.php on line xy
Bei mir ist dieses Problem aufgetreten weil sich da ein $ eingschmuggelt hatte wo es nichts zu suchen hatte.

Vorher $this->free_result($this->$query_id);

Nacher $this->free_result($this->query_id);

Wie man sieht genügt es das $-Zeichen zu entfernen.

30 Aug 2007, 11:14

XML Dokumente mit Namespaces in PHP5/SimpleXML verarbeiten

SimpleXML ist was feines. Damit lassen sich XML Dokumente ohne viel Aufwand bearbeiten, leider hat das ganze einen kleinen Haken.

Namespaces! Richtig, SimpleXML kann Namespaces zwar verarbeiten aber dadurch wird die Bedienung etwas verwirrend und leider ist das ganze auch nicht gut Dokumentiert.

Ein kleines Beispiel, gegeben sei folgende XML Datei: <XmlResultSet version=“1.0.0” xmlns=“http://www.gauner.org/api" xmlns:bml=“http://www.bla.net/bml" xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=“http://www.gauner.org/api/schema.xsd"> <bml:description>This is an API</bml:description> <bml:name>api</bml:name> <bml:Member> <AnEntry> <bml:name>Blabla</bml:name> </AnEntry> </bml:Member> </XmlResultSet>

So, jetzt mal angenommen ich will auf Xml->bml:Member->AnEntry->Name zugreifen. Ohne Namespaces ist das mit SimpleXML ganz einfach: Xml->Member->AnEntry->Name. Aber das lustige an Namspaces ist, dass die jeweils anderen Namespaces ausgeblendet werden. D.h. SimpleXML sieht alles im Namespace “bml” erstmal nicht.

Ok, dafür gibts eine Lösung: Man kann mit Element->children(‘namespace-url’) explizit auf die Namespaces zugreifen, aber dabei gibt es zwei Fallen. Zum einen muss man unbedingt die URL des Namespaces angeben, nicht etwas den Namen des Namespace, und zum anderen ist es wichtig zu beachten, dass dann eben die anderen Namespaces augeblendet werden, und man ggf. wieder in den Default Namespace (mit ->children(“)) wechseln muss.

Wenn ich jetzt in obigem Beispiel auf <bml:name> Zugreifen will sähe der korrekte Code dann etwa so aus: $xml = new SimpleXMLElement($source); $name = $xml->children(‘http://www.bla.net/bml')->Member->children('')->AnEntry->children('http://www.bla.net/bml')->name;

Siehe dazu auch den Eintrag bei SitePoint.

20 Aug 2007, 14:59


 Kernkraftwerkbetriebsführungssofware <- OMFG ;D

16 Jul 2007, 10:29

Aus jHTTPd wird libjhttpd

Nachdem ich den Code zu meinem einfachst-Webserver jHTTPd (HTTP/1.0, Multithreading, IPv6- und UTF-8-Support) in wesentlich mehr Projekten weiter verwendet habe, als zunächst geplant, habe ich mich entschlossen den Code nochmals zu überarbeiten, ein wenig refactoring zu betreiben und als Bibliothek umzuarbeiten.

Der Webserver kann jetzt auch ordentlich binäre Multipart POST Requests verarbeiten. Ein kleines Missverständnis zwischen mir und den Java Streams hat dafür gesorgt, dass es vorher nicht funktioniert hat.

Bytes nach String und wieder zurück zu casten geht selten gut ;)

Die Bibliothek ist so angelegt, dass man den bestehenden Code nicht ändern muss - wobei das für eine Bibliothek selbstverständlich sein sollte.

Im Package webserver.sample befindet sich ein Beispiel dafür wie man die Bibliothek verwenden kann.

Ähnlich wie beim Apache-Webserver existieren ein paar Hooks die es erlauben an verschiedenen Stellen der Request Verarbeitung einzugreifen und die Daten entsprechend zu manipulieren.

Eine lauffähige Instanz des Webservers erzeugt man mit folgendem Code:

Config config = new Config(); // read the config try { config.readConfig(Config.CONFIG_FILE); } catch (IOException e) { e.printStackTrace(); } // check command line arg count if (args.length > 0) { // parse args config.setPort(args[0]); } WebServer ws = new WebServer(config, new SampleHttpRequestFactory()); Thread t = new Thread(ws); t.start();

Weiterhin muss man in einer Klasse die Schnittstelle IHttpRequestFactory implementieren und dort die, ebenfalls zu implementierende, Klasse die von HttpRequest erbt, angeben.

HttpRequest bietet drei sog. Hooks.

  • postConnect() - wird aufgerufen sobald der Client die Verbindung hergestellt hat, aber bevor irgendetwas weiter passiert ist. Hier könnte man z.B. überprüfen ob der Client auf einer Blacklist steht, bzw. aus einem nicht zulässigen Netzwerk kommt und die Verbindung schliessen bevor weitere Ressourcen verbraucht werden.
  • postRequest() - wird aufgerufen nachdem der Request des Clients, d.h. inkl. evtl. vorhandenem POST-Body, verarbeitet wurde. Hier sollte eigentlich fast der gesamte benutzerspezifische Code landen.
  • preClose() - wird aufgerufen direkt bevor die Verbindung zum Client geschlossen wird und nachdem die Antwort gesendet und der Request geloggt wurde. Zu diesem Zeitpunkt besteht keine Garantie dafür, dass die Verbindung zu Client noch existiert.
Die Klasse HttpRequest bietet neben den Hooks noch eine Reihe von Methoden die den Zugriff auf die Daten des Requests ermöglichen.

Die wichtigsten wären:

  • getArgument() - um die komplette Liste der Argumente zu erhalten. Also POST und GET Argumente.
  • getMultiparts() - um die evtl. vorhandenen Multipart Teile eines POST Requests zu erhalten.
  • getRemoteAddress() - um die IP des Clients zu erhalten sowie getRemotePort() um den dazugehörigen Port zu erhalten. Diese zwei Felder sind die einzigen die während postConnect() schon gültige Daten enthalten.
  • getRequestHeader() - um den verarbeiteten Header auszulesen.
  • getResponseHeader() - um auf den Response Header zuzugreifen.
Für weitere Details möchte ich direkt auf den Quellcode verweisen. Fragen und Anmerkungen bitte über die Kommentarfunktion.

Den Quellcode und den Download gibts hier: libjhttpd.

16 Jul 2007, 10:01

jSpellCorrect überarbeitet

Der Java Spelling Checker, jSpellCorrect, wurde von mir nochmal ein wenig überarbeitet. Jetzt kommt er prinzipiell mit beliebig großen Trainingsdaten zurecht. Vorher existierte eine, unnötige, künstliche Beschränkung.

Download jSpellCorrect.

Allerdings existiert weiterhin die Einschränkung, dass die HashMap der Wahrscheinlichkeiten in den Arbeitsspeicher passen muss. Hier bin ich allerdings noch nicht an die Grenzen gestossen.

Eine Möglichkeit dies zu umgehen, wäre ein Teil der Daten auf der Festplatte zu speichern, aber dies ist mir im Moment zu umständlich. Bei Bedarf werde ich das nachrüsten.

05 Jul 2007, 16:02

Warum sich IPv6 in den nächsten 5 Jahren durchsetzen wird

  • Weil immer mehr Anwendungen (Apache, Mailserver, etc.) IPv6 fähig sind
  • Weil Windows Vista IPv6 standardmäßig aktiviert hat.
  • Weil meine Server alle IPv6 sprechen ;)
  • Weil China, mit seiner aufstebenden Wirtschaft, gerade einmal soviele IPv4 Adressen hat wie die Universität von Californien.
  • Weil dieICAAN massiv für IPv6 werben will.
Und wenn ich mich geirrt habe ist es auch nicht schlimm, denn IPv4 ist auch was tolles.

28 Jun 2007, 08:41

Eclipse macht unter Linux nur Probleme ...

Seit einiger Zeit macht Eclipse unter Linux nur noch Probleme.

Nicht nur, dass es extrem viel Speicher verbraucht, dank SWT/GTK, es stürtzt auch reproduzierbar beim öffnen das Auto-Complete Dialog ab und das neue Europa Release verabschiedet sich gar direkt wenn ich den  Software Update Dialog öffne.


Es wird Zeit, das ich mich mit Netbeans beschäftige. Das läuft deutlich besser, nur mit der Bedienung muss ich mich noch anfreunden.

24 Jun 2007, 12:42

Kernel bauen unter Debian

Aus aktuellem Anlass:

Wie baue ich unter Debian einen neuen Linux Kernel?

Antwort: Ganz einfach

Achtung: Ich beschreibe hier nicht den “Debian-way”, sondern so wie ich es immer mache.

# root werden
# in das build Verzeichnis wechseln
cd /usr/src
# den aktuellen Kernel runterladen, anpassen!
wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-</pre>

# den Kernel entpacken, anpassen!
tar xvfj linux-
# den alten Symlink entfernen
rm linux
# den neuen Symlink erstellen
ln -s linux- linux
# ins Verzeichnis mit den aktuellen Quellen wechseln
cd linux
# die .config des aktuellen Kernels kopieren
cp /boot/config-`uname -r` ./.config
# die alten Optionen übernehmen
make oldconfig
# ggf. die Config anpassen
make menuconfig
# compilieren
make -j10 &amp;&amp; make -j10 modules
# installieren
make install &amp;&amp; make modules_install
# grub aktualisieren

21 Jun 2007, 11:29

Dovecot 1.0.1 veröffentlicht

Der IMAP4/POP3-Server Dovecot wurde vor einigen Tagen in der Version 1.0.1 veröffentlicht.

Die Liste der Änderungen ist relativ kurz und es handelt es sich hauptsächlich um einige kleinere Bugfixes.

Hier das Changelog und der Download.

20 Jun 2007, 07:48

Eclipse unter Linux ist super lahm!

Ich frage mich wirklich warum Eclipse unter Linux so super lahm sein muss.

Offensichtlich hängt das ganze mit SWT zusammen und Abhilfe ist auch möglich, aber mir ist es nicht gelungen SWT/Fox zu installieren. Das hängt wahrscheinlich auch damit zusammen, dass das SWT/Fox Projekt seit einiger Zeit inaktiv zu sein scheint.

Bei nächster Gelegenheit werde ich mir mal Netbeans anschauen, das scheint ja nicht ganz so schrecklich langsam zu sein …

18 Jun 2007, 11:50

Rechtschreibkorrektur in Java

Nach der Lektüre des überaus interessanten Artikels über einen einfachen Algorithmus zur Rechtschreibkorrektur von Peter Norvig, habe ich beschlossen den abgefahrenen Python Code in Java zu übersetzen. Nach ein paar Versuchen hat es auch schon geklappt. Das Ergebnis des ganzen gibt es ab sofort unter dem Namen jSpellCorrect zu bewundern.


Nachdem Peter Norvig seine Seite aktualisiert hat muss ich sagen, dass ich ein wenig schockiert bin: Aus einem einfachen 21 Zeilen Python Programm werden über 350 Zeilen Code in Java ... autsch ;)

07 Jun 2007, 08:12

Gauner on IPv6

Der Server ist seit gestern auch provisorisch über IPv6 via SixXS zu erreichen.

Vorerst dürfte nur der Mailserver zu 100% IPv6 tauglich eingerichtet sein.

Der Apache ist zwar auch schon für IPv6 vorbereitet, die vHosts müssen aber noch entsprechende konfiguriert werden.

Bei den weiteren Diensten ist die IPv6 Unterstützung bis jetzt noch unklar, wird aber nach Möglichkeit bald folgen.

31 May 2007, 22:40

jPatchLib 0.0.1b

So, hier ist die nächste Version von jPatchLib: 0.0.1b.

Die Probleme mit den Leerzeilen sollten jetzt erledigt sein und ich habe die Dokumentation hinzugefügt: JavaDoc.

Mehr Infos. Weitere Projekte.

31 May 2007, 13:32

Patch Library für Java - jPatchLib

Nachdem ich lange vergeblich versucht habe eine Implementation von GNU Patch für Java zu finden bin ich zu dem Schluss gekommen, dass es wohl einfacher ist eine selbst zu schreiben.

Das Ergebniss findet sich unter http://developer.gauner.org/jpatchlib/.

Ein paar Sachen stehen noch auf meiner ToDo Liste, aber für einen ersten Eindruck sollte es reichen.

Was noch aussteht:

  • Dokumentation

  • Probleme mit Leerzeilen beheben

Ansonsten natürlich viel Spaß damit.

23 May 2007, 10:24

Patch Library für Java?

Es gibt zwar ein paar Implementierungen von diff für Java, aber eine patch Implementierung konnte ich nicht finden.

Sollte ich doch noch fündig werden, werde ich darüber berichten.

14 May 2007, 09:05

Skype aka the Worlds biggest Botnet

Ein sehr interessantes und vor allem detailiertes Essay zur Sicherheit von und mit Skype gibt es hier: Skype inSecurity Essay.

Jedem Netzwerkadministrator, Netzwerkverantwortlichen, Sicherheitsbewusstem Benutzer und allen auch nur halbwegs Paranoiden sei das dringend empfohlen.

Update 18.08.07: Siehe auch diesen Beitrag über die aktuellen Probleme mit  Skype.

12 May 2007, 14:26

Munin Plugins für Dovecot und die Auth-Facility

Ich habe im Munin Plugin Exchange (lokaler Mirror) zwei praktische Munin Plugins zur Verfügung gestellt.

Zum einen ein Plugin um die Logins und Verbindungen zum Dovecot IMAP/POP3-Server zu überwachen … Dovecot Day

… und zum anderen eine verbesserte Version das auth Plugin um Logins und fehlgeschlagene Versuche der Auth-Facility zu überwachen.

Auth Day

09 May 2007, 19:52

Eclipse: Dummer Update-Manager

Warum ist der Update-Manager von Eclipse eigentlich so blöd?

Kaum habe ich Eclipse nach der Installation der neusten Updates neu gestartet, fängt er wieder von Vorne an und will neue Updates installieren. Kann der das nicht auf einmal?

Ausserdem frage ich mich auch warum der nach jedem Start ewig braucht bis er die Updates gefunden hat? Da liese sich einiges verbessern …

27 Apr 2007, 09:29

Essence of Software Design (Java)

Ich habe mir vor einiger Zeit einige wichtige Design-Prinzipien für das Software Design, insb. in Java, zusammengefasst und einige oft gebrauchte Design-Patterns und Entwurfsrichlinien erläutert.

Zu finden ist das ganze unter The Essence of Software Design.

Die wichtigsten Prinzipien:

  • Open-Closed-Principle (OCP) - A class should be open for extension but closed for modification.
  • Liskov Substitution Principle (LSP) - An instance of a class should function as an instance of its superclass.
    Typical violations of LSP:
    • Derivates that override a method of the super-class by an empty method potentially violate LSP
    • Derivates that throw additional exceptions violate LSP

  • Dependency Inversion Principle (DIP) - High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions. DO NOT DEPEND ON A CONCRETE CLASS. All relationsships in a program should terminate on an abstract class or an interface.

21 Apr 2007, 12:41

Jabber Clients mit Jingle - Fehlanzeige!

Ich bin seit einiger Zeit auf der Suche nach einer brauchbaren alternative zu Skype.

GoogleTalk ist ein super Ansatz, aber ich hätte lieber etwas das auch unter Linux läuft.

Google war zwar so nett die Jingle Spezifikation zu veröffentlichen, aber so wie es aussieht gibt es im Moment keinen Client der das vernünftig implementiert.

  • PSI scheint kein Jingle zu unterstützen
  • Pidgin aka Gaim soll zwar “bald” Jingle Support haben, aber wann das konnte ich nicht in Erfahrung bringen
  • Cocinella scheint Jingle zu unterstützen, aber diesen Client konnte ich noch nicht testen

Schade, kein ordentlicher Jingle/VoIP Client unter Linux.

19 Apr 2007, 10:42

Firefox AdBlock Code killt TinyMCE

Den meisten Wordpress Benutzer dürfte TinyMCE ein Begriff sein, und wenn nicht, dann haben sie es zumindest schon einmal gesehen. Das ist der AJAX Editor der sich in neueren Wordpress Versionen unter dem “Visual Editor” verbirgt.

Vor einiger Zeit gab es auf der Hilfe-Seite von Firefox eine AdBlock Sektion. Soweit ich weiss wurde die inzwischen entfernt, aber ich nutze den Code für die userContent.css seit dem und bin damit eigentlich extrem zufrieden, da er die Anzahl der angezeigten Ads auf eine sehr erträgliche Anzahl reduziert. Nur gegen Layer-Ads fehlt mir noch der entsprechende Block-Code, aber das ist eine andere Geschichte. Das Vorteil von dem userContent.css Code ist auch, dass es auf der Server Seite kaum zu erkennen ist ob die Ads angezeigt werden oder nicht, da diese Datei einfach ein zusätzliches CSS Darstellt das beim rendern vom Browser berücksichtigt wird.

Das Problem an dieser Lösung ist, dass es ab und zu Kollateralschäden kommt. Bis jetzt hat mich das nicht weiter gestört, aber seit TinyMCE in Wordpress integriert ist stört es schon ein wenig wenn der Editor nicht benutzbar ist. Daher habe ich den AdBlock-Code mal untersucht um die Bösewichte zu finden die TinyMCE zerschiessen.

Die Übeltäter waren folgende Anweisungen:

iframe[src=“/adv”], img[src=“/adv”], img[src*=“/adx”],

Hier gibts die korrigierte Datei: AdBlock für Mozilla Firefox

17 Apr 2007, 07:13

Top 5 Eclipse Plugins

Meine wichtigsten Eclipse Plugins:

Die “Plugins” die sowieso in der Eclipse-Distribution enthalten sind, bzw. von der Eclipse Foundation direkt gepflegt werden liste ich hier nicht auf. Das wären z.B. JDT, CDT, etc.

16 Apr 2007, 22:06

Version 0.3 von jTodoList

Die neue Version von jTodoList bietet jetzt auch die Möglichkeit die Todo-Liste als Treemap, gewichtet nach Priorität oder Risiko, darzustellen.

Für das nächste Release steht eine Überarbeitung der GUI an. Der Code gefällt mir so im Moment nicht.

Download: tar.bz2 / zip

Homepage: jTodoList

16 Apr 2007, 12:34

Top 5 Java Bibliotheken

Hier nur kurz meine 5 wichtigsten Java Bibliotheken:

Ein weiterer Kandidat für diese Liste ist die TreeMap Library, aber da ich sie selbst noch nicht getestet habe muss ich erstmal sehen was sie zu bieten hat.

P.S.: DDL = direkter Download

16 Apr 2007, 07:38

PowerNow! unter Linux für Athlon64 X2 3800+ auf Abit AX8 V2.0

Da einige Mainboardhersteller die ACPI Tabellen ihrer Produkte offenbar leider etwas schlampig pflegen muss man als Linux Nutzer teilweise selbst Hand an die DSDT-Tabellen legen.

Zwar gibt es beim Linux/ACPI-Projekt einige korrigierte DSDT-Tabellen, aber da mein Mainboard nicht dabei war musst ich selbst den Compiler anwerfen und mein Glück versuchen.

Das Ergebniss will ich der Welt nicht vorenthalten, vielleicht kann ja sonst noch jemand was damit anfangen. Zu finden ist das ganze hier: Fixed ACPI DSDT Tables for Linux.

Ich muss aber dazu sagen, dass ich für nichts garantiere. Diese DSDT läuft bei mir schon über ein halbes Jahr wunderbar, aber es kann gut sein, dass es auf einem anderen System zu ernsten Problemen - bis hin zu Hardware Schäden - kommen kann.

11 Apr 2007, 20:31

WEP gesicherte WLANs in weniger als einer Minute knacken

Wie heise vor ein paar Tagen berichtet hat, haben es ein paar meiner Komolitonen an der TU Darmstadt geschafft die WEP Verschlüsslung in unter einer Minute zu knacken - zumindest in 50% aller Fälle.

Gestern lief dazu auch ein Bericht im Nachtmagazin der ARD den es sogar Online gibt. Falls der Link nicht funktioniert kann man das ganze auch über tagesschau.de unter Multimedia finden.

07 Apr 2007, 14:22

jPOPc - Java POP3 Client veröffentlicht

Soeben habe ich unter jPOPc den angekündigten Java POP3 Client veröffentlicht.


07 Apr 2007, 14:13

Breakpoint 2007 hat begonnen!

Vor kurzem hat in Bingen die alljährliche Demo Compo Breakpoint begonnen.

Nach dem Wegfall einiger Sponsoren mussten die Eintrittspreise leider kräftig erhöht werden, was mich ehrlich gesagt, davon abgehlaten hat dieses Jahr einmal persönlich teilzunehmen. Naja, so bleibt die Szene unter sich ;)

Wir können wieder mal gespannt sein wer dieses mal als Sieger aus den einzelnen Veranstaltungen hervorgeht.

07 Apr 2007, 14:12

jHTTPd - Java Webserver veröffentlicht

Soeben habe ich unter jHTTPd den länger angekündigten simplen Java Webserver veröffentlicht.

Download Binary / Source

06 Apr 2007, 10:26

jUPnP - Java UPnP Beispiel Implementierung veröffentlicht

Soeben habe ich unter jUPnP eine UPnP-Implementierung in Java veröffentlicht.

Die Anwendung implementiert zwar nur ganz konkrete Funktionen, ist aber sicherlich für einige Personen trotzdem interessant wenn es um die Implementierung von UPnP in Java geht.

Download Binary / Source

06 Apr 2007, 10:25


Mir war lange Zeit unklar was der Unterschied zwischen SAX (Simple-API-for-XML) und DOM (Document Object Model) ist.

Ich möchte das hier nochmal kurz zusammenfassen:

Ein DOM-Abbild einer XML-Struktur liegt i.d.R. komplett im Speicher und lässt sich so sehr bequem manipulieren und auslesen, benötigt aber unter Umständen sehr viel Speicherplatz.

Bei SAX definiert der Entwickler sog. Callback-Handler die bei bestimmten Ereignissen, d.h. XML-Tags (z.b. <html>) aufgerufen werden. So wird nur ein Bruchteil der XML-Datei im Speicher vorgehalten und es wird damit möglich auch sehr große XML-Datein zu parsen.

Man stelle sich vor man bekommen eine 1,2 GB große Datei mit allen Zugverbindungen in Deutschland und will die komplett in den Speicher laden … (Alles schon vorgekommen).

25 Mar 2007, 09:27

FlexiCrypt 1.1 veröffentlicht

Die neue Version 1.1 von FlexiCrypt macht das Programm zu den neuen Versionen der zugrunde liegenden Bibliotheken kompatibel.

Da die Entwickler des FlexiProvider, entgegen aller “Best Practices”, die exportierte API geändert haben, musste ich einige Stellen in FlexiCrypt anpassen.

Durch die neue FlexiProvider Version 1.3.1p1 sind ein paar neue Algorithmen hinzugekommen. Details gibts auf der FlexiProvider Homepage.

25 Mar 2007, 09:22

jTodoList 0.2 veröffentlicht

Gestern Abend habe ich die Version 0.2 von jTodoList veröffentlicht.

Die wesentliche Neuerung sind die neuen Export-Filter.

Weiterhin wurde der Code für weitere Ex- und Import Filter vorbereitet. [UML]

22 Mar 2007, 22:22

Singleton in D

Das ist wohl der erste “self containing singleton” (so habe ich ihn getauft) in D:

 8:    /// Singleton instance.
 9:    private static SceneManager singleton;
11:    /// No public need for this.
12:    private static this() {
13:        singleton = new SceneManager();
14:    }
16:    /// Get signleton instance.
17:    public static SceneManager opCall() {
18:        if(singleton == null)
19:            singleton = new SceneManager();
20:        return singleton;
21:    }
z.B.: SceneManager().registerScene(new DebugScene()); SceneManager().registerScene(new StarfieldScene());

06 Feb 2007, 16:49

jTodoList veröffentlicht!

Ich habe vor kurzem eine kleine, aber feine To-Do-Liste ein Java geschrieben.

Unter Windows gibt es das hervorragende Programm ToDoList von Abstract Spoon, aber unter Linux läuft das leider nicht.

Da ich aber nunmal beide System einsetze wollte ich auch unter Linux eine Möglichkeit meine ToDo zu bearbeiten.

Dabei rausgekommen ist dieses nette Programm.

Zu finden ist das ganze unter diesem Link. Dort gibts auch einen Screenshot und weiter Informationen.

Ach ja, es wird Java 5+ benötigt und das ganze steht unter GPL.

23 Nov 2006, 11:10

Java Strings oder Wie-ich-meine-Perfromance-verbaue

Kürzlich musste ich feststellen, dass es keine gute Idee ist eine größere Menge an Daten in einem String zu puffern. Ich finde es etwas schwierig zu umschreiben aber so sieht der Beispiel-Code aus:

String str = ""
while((buffer = br.readLine() != null) {
  str += buffer;
return str;

Das Problem an dieser Konstruktion ist, dass bei jedem Schleifendurchlauf - und das waren in dem Fall einige - jede Menge Objekte anglekt werden. Für die + Operation zwischen Strings (Konkatenation) wird von Java in etwa folgener Code generiert:

str = new StringBuilder().append(str).append(buffer).toString();

Eventuell wird das interne Char-Array des StringBuilders beim zweiten append nochmal vergrößert, d.h. ein neues anlegen, das halt hineinkopiert, das alte löschen. Dabei muss eine Menge Speicher allokiert und wieder freigegben werden, jeden Menge neue Objekte werden erzeugt, sprich: es entseht ein riesiger Overhead. Das kommt insbesondere dann zum tragen wenn die der BufferReader br gerade dabei ist eine Textdatei von vielleicht 5MB einzulesen, z.B. Base64 kodierte Binärdaten. Die ganze Operation hat so je nach System ca. 10-120 Minuten benötigt.

Einen kleinen Tipp und ein paar Änderungen später hat das ganze nur noch ca. 1,2 Sekunden benötigt. Der oben genannte Code wurde einfach in folgendes geändert:

StringBuilder sb = new StingBuilder()
while((buffer = br.readLine() != null) {
return sb.toString();

Da hier der StringBuilder direkt benutzt wird, ergibt sich ein beachtlicher (!) Performanz-Gewinn.

16 Oct 2006, 10:26

FlexiCrypt 1.0 veröffentlicht

Soeben haben wir unter developer.gauner.org/flexicrypt/ das universelle crypto toolkit FlexiCrypt veröffentlicht.

Es ist das Ergebniss einer 6 monatigen Entwicklung und ermöglicht es dem Benutzer beliebige Dateien zu ver- und entschlüsseln, zu signieren und verifizieren. Ausserdem enthällt es eine komplette Schlüsselverwaltung.

Das besondere daran ist, dass es auf den FlexiProvider vom Fachbereich Informatik der TU Darmstadt aufsetzt und damit auch Zugang zu den neusten Algorithmen bietet. Darunter z.B. ECC, Number Field Cryptography.

20 Sep 2006, 10:59

Kernel 2.6.18 released!


Nach dem rc7 ist es endlich soweit. Das hat diesmal irgendwie ziemlich lange gedauert.

Endlich ist er da: Source, Changelog

28 Apr 2006, 12:43

VoiceCode - Coden ohne finger

Endlich mal eine innovative Idee für Programmierer: Coden per Voice Tool. So kann man Sehnenscheidentzündungen vorbeugen und falls man sich doch mal beide Arme bricht, tut das auch keinen Abbruch. Im Moment ist das ganze aber nur für Python verfügbar.

VoiceCode lets a programmer dictate code in a more natural way, Désilets says, rapidly translating their utterances into awkward programming syntax. For example, in order to write “if (currRecNum < maxOffSet)” a VoiceCode user only needs to say: “if current record number is less than max offset then”. Traditional voice-recognition programs could require nearly 50 individual words to be dictated.
Link: http://voicecode.iit.nrc.ca/

24 Mar 2006, 11:17

Link: Entwickler über Programmiersprachen


In den meisten fällen kann ich die Meinung teilen. Durchlesen lohnt sich.

17 Feb 2006, 11:05

Kent Beck in Frankfurt

Kent Beck kommt nach Frankfurt, einer der Mitbegründer des XP (eXtreme Programming). Leider ist die Teilnahmegebühr von EUR 725,00 etwas zu hoch für Privatpersonen. Mal sehen, ob man das was über die Firma drehen kann - immerhin gibts bis 10.03. noch 25% Frühbucherrabatt. Heise Newspost

15 Feb 2006, 12:37

Objektorientiertes If (Ruby)

wtf? Objektorientiertes If? Ok, das kennen wir:

if (1==2) then
  puts '1==2'
elsif (1==3) then
  puts '1==3'
  puts 'neither nor'

aber warum nicht so:

(1==2).then do
  puts '1==2'
end.elsif(1==3) then
  puts '1==3'
end.else do
  puts 'neither nor'

way cool, mehr solcher snippets gibts auf dem “hier” Link: hier. Happy coding!

08 Feb 2006, 15:00

Endlich mal ein echter Grund auf Linux zu wechseln...

hier nur die Links (hoffentlich selbsterklärend ™):

  1. http://www.novell.com/linux/xglrelease/
  2. http://en.opensuse.org/Xgl
  3. http://www.freedesktop.org/Software/Xgl

07 Feb 2006, 22:13

Ruby, Apache + FastCGI

Ruby hat mich begeistert, Rails hat mich tief beeindruckt und FastCGI hat mich schwer enttäuscht. Man sollte denken, dass es mit dieser Anleitung nicht weiter schwer sein sollte Ruby on Rails über FastCGI auf dem Apachen zum laufen zu bringen. Weit gefehlt. Aus irgendeinem Grund war FastCGI der Meinung es müsse mich verarschen. FastCGI: incomplete headers (35 bytes) received from server “/path/to/yourapp/public/dispatch.fcgi” Dank dieses Blogs und diesem Hinweis habe ich es dann doch noch zu einem guten Ende gebracht.

Ich weiss noch nicht genau ob es jetzt an der Datenbankkonfiguration oder den verweisten Sessions lag, aber nachdem ich mich um beides gekümmert hattte lief endlich alles.

03 Feb 2006, 08:43

Let Java retire from the spotlight of web applications in dignity

Hier gehts zum Interview mit dem RoR Entwickler David Heinemeier Hansson: Hier


01 Feb 2006, 09:47

Ruby Links

Wichtige Links zu Ruby on Rails RubyForBeginner API-DOC AccessControlListExample Ruby on Rails Wiki

25 Jan 2006, 10:29

Cute Code Collection

Steves ‘Cute Code’ Collection, faszinierend was sich Menschen so aussdenken.

x ^= y ^= x ^= y ;
Vertauschen von zwei Variablen ohne eine dritte herziehen zu müssen.

16 Dec 2005, 09:41

try ruby!

Ein nettes interaktives Tutorial zur Ruby Programmiersprache findet man hier: http://tryruby.hobix.com/

Warum? RubyOnRails 1.0 released! Gas geben in der Web Entwicklung. Mehr Infos unter: http://rubyonrails.org/ (unbedingt die Tutorials anschauen)