Facebook
Twitter
Google+
Kommentare
0

Punycode, IDN: Welche Probleme es bei Umlaut-Domains in PHP gibt

Naja, eigentlich betrifft es nicht nur Umlaut-Domains hier in Deutschland, sondern allgemein alle Internationalized Domain Names auf der Welt. Also, was passiert wenn wir eine E-Mail an info@müller.de verschicken möchten? Was passiert wenn wir eine an die griechische Domain info@παράδειγμα.δοκιμή verschicken wollten? Was passiert wenn wir auf Port 80 des Webservers von www.müller.de zugreifen wollen? Richtig, alles wird fehlschlagen.

Erstmal zum Grundproblem. Das Internet ist alt, und damals hat noch niemand daran gedacht, dass es auch andere Sprachen als Englisch gibt, deshalb baut alles auf ASCII auf, also mehr oder weniger alles was auf einer englischen Tastatur zu finden ist. Das Domain Name System ist sogar noch strikter und erlaubt nur die 26 lateinischen Buchstaben, die Zahlen 0-9 und den Bindestrich. Das wars!

Man kam also auf die Idee, den Zeichensatz für Domains vergrößern zu wollen. Das interessante daran ist nun aber dass dies geschehen sollte ohne alle Server und Netzwerkgeräte austauschen zu müssen, man benötigte also eine Art Workaround. Deshalb wurde 2003 Punycode eingeführt. Mit Punycode kann man eine Domain, die beispielsweise Umlaute enthält, in eine Domain umwandeln die nur die oben erwähnten 37 zeichen enthält. Aus müller.de wird xn--mller-kva.de . Wie genau diese Umsetzung stattfindet kann im entsprechenden RFC 3492 nachgelesen werden, nur soviel: xn-- deutet auf eine Punycode-Domain hin. Die Umlaute werden angehängt, in diesen angehängten Zeichen ist die Position und der Umlaut codiert.

Alle Browser beherrschen natürlich Punycode, sodass man gefahrlos www.müller.de in die Adresszeile eingeben kann, und der Browser arbeitet dann intern mit der Punycode-Schreibweise wenn er mit dem DNS-Server oder dem Webserver kommuniziert.

Was ist aber mit PHP? Aktuell ist die Unterstützung nicht eingebaut, was man leicht überprüfen kann:

<?php
var_dump(dns_get_record('www.phpgangsta.de', DNS_A));
var_dump(dns_get_record('www.müller.de', DNS_A));

Die Ausgabe sieht wie folgt aus:

array(1) {   [0]=>
  array(5) {
    ["host"]=>
    string(17) "www.phpgangsta.de"
    ["type"]=>
    string(1) "A"
    ["ip"]=>
    string(12) "85.214.28.26"
    ["class"]=>
    string(2) "IN"
    ["ttl"]=>
    int(532)
  }
}

Warning: dns_get_record(): Dns Query failed in punycode.php on line 4

Call Stack:
    1.0016     332464   1. {main}() punycode.php:0
    1.0556     332608   2. dns_get_record() punycode.php:4

bool(false)

Das selbe gilt übrigens auch für alle anderen Netzwerk-Funktionen wie fsockopen(), gethostbyname(), mail(), alle Funktionen die mit dem HTTP-, FTP- oder SSH2-Wrapper umgehen können, z.B.

file_get_contents('http://www.müller.de')

Wir müssen uns also selbst darum kümmern. Dazu nutzen wir einfach die idna_convert Klasse (bzw. Net_IDNA) von Matthias Sommerfeld. Mit 3 Zeilen Extracode können wir auch mit Umlaut-Domains kommunizieren:

require_once('idna_convert.class.php');

$IDN = new idna_convert();
$output = $IDN->encode('www.müller.de');

var_dump(file_get_contents('http://'.$output));
var_dump(dns_get_record($output, DNS_A));
var_dump(gethostbyname($output));

Wenn man nun konsequent überall, wo Domain Namen auftreten, die Punycode-Konvertierung anwendet, gibt es auch keine Probleme mehr mit IDNs. Also überprüft euren Code darauf ob ihr eventuell ein Problem habt wenn ihr E-Mails an Nutzer verschickt etc.

flattr this!

Über den Autor

PHP Gangsta

Der zweitgrößte deutsche, eher praxisorientierte PHP-Blog von Michael Kliewe veröffentlicht seit Mitte 2009 Artikel für Fortgeschrittene.

Link erfolgreich vorgeschlagen.

Vielen Dank, dass du einen Link vorgeschlagen hast. Wir werden ihn sobald wie möglich prüfen. Schließen