Zeichenkodierung/Webserver

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Inhaltsverzeichnis

[Bearbeiten] In Richtung Client

Ein Webserver teilt einem Client (z.B. Browser) in einem HTTP-Header namens Content-Type (Content = Inhalt) mit, um was für Daten es sich in einer Response auf einen Request handelt. Für alle Text-Dokumente, inklusive HTML-, CSS- und JavaScript-Dokumente, beginnt der Media-Type mit text/... und es kann der optionale Parameter charset mitgegeben werden.

Das Senden von HTTP-Headern kann man auf vielfältige Weise veranlassen. Sie können im Webserver konfiguriert werden und/oder von eingebetteten Systemen (beispielsweise PHP) explizit angegeben werden. Lesen Sie dazu bitte in den Abschnitten der jeweils verwendeten Systeme nach oder in der systemspezifischen Dokumentation.

Beispiel: HTTP-Response-Header für ein HTML-Dokument
HTTP/1.1 200 OK Date: Fri, 26 Mar 2010 10:25:40 GMT Content-Length: 42 Content-Type: text/html; charset=utf-8 Last-Modified: Fri, 26 Mar 2010 10:01:43 GMT <html>...

Nicht immer stehen HTTP-Header zur Verfügung, beispielsweise dann nicht, wenn Dokumente lokal abgespeichert wurden. Unter anderem für diesen Fall kann eine charset-Angabe auch in einem meta-Element stehen.

Beispiel: HTML-Dokument
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Beispiel</title> </head> <body> ... </body> </html>

Die HTML5-Spezifikation schlägt ein neues meta-Element vor. Dieses muss in den ersten 1024 Bytes eines Dokuments stehen, also sollte es ziemlich am Anfang des head-Elements platziert werden. Die bisherige Variante kann allerdings auch weiterhin verwendet werden.

Beispiel: HTML5-Dokument
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Beispiel</title> </head> <body> ... </body> </html>

Für XML und XHTML gibt es die XML-Deklaration, die das Attribut encoding kennt, dessen Default-Wert UTF-8 ist. Die XML-Deklaration ist optional. Da die aktuellen Browser XHTML nicht nach den XML-Regeln sondern wie HTML behandeln, kann man auf die XML-Deklaration verzichten. Zugunsten des IE 6 sollte man dies auch, da er sich sonst in den Quirks Mode schaltet.

Beispiel: XHTML-Dokument
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Beispiel</title> </head> <body> ... </body> </html>

Der Vollständigkeit halber sei erwähnt, dass es auch für das a-Element (für Links) ein charset-Attribut gibt, mit dem die Zeichencodierung für das Zieldokument angegeben werden kann, was jedoch ungebräuchlich ist.

Beachten Sie: Wenn mehrere Angaben vorhanden sind, gilt diese Rangfolge:
  1. HTTP-Header Content-Type
  2. XML-Deklaration (bei XHTML)
  3. Meta-Element
  4. charset-Attribut in Links

Für CSS-Dokumente gilt:

  1. HTTP-Header Content-Type
  2. @charset-Regel im Dokument
  3. charset-Attribut im link-Element
Beachten Sie außerdem, dass Browser zu raten anfangen, wenn sie keine Angabe zur Zeichencodierung finden. Das Ergebnis ist unvorhersehbar und mitunter sicherheitskritisch. (Suchen Sie nach „utf-7 security“, wenn Sie mehr dazu wissen wollen.) Durch Angabe einer korrekten Codierungsinformation lassen sich diese Probleme vermeiden.

[Bearbeiten] In Richtung Server

[Bearbeiten] POST

Ein Formular wird üblicherweise von den Browsern in der Codierung versendet, die für die Seite angegeben wurde, in dem es steht. Wenn also der Server eine Webseite mit einem Formular ausliefert, die in UTF-8 codiert ist, wird der (Antwort-)Request mit den Formulardaten ebenfalls UTF-8-codiert werden.

Für das form-Element existiert auch das Attribut accept-charset, in dem Sie eine Liste von Zeichencodierungen angeben können. Es ist jedoch empfehlenswert nur eine einzige Angabe zu machen. Es gibt keine Regel oder irgendein etabliertes Verfahren, mit der/dem ein Client dem Server die verwendete Codierung mitteilen kann. Der Server ist deshalb darauf angewiesen, dass der Client „von selbst“ die gewünschte Codierung verwendet. Wenn für accept-charset nun mehr als ein Wert angegeben wird, kann sich der Client irgendeinen raussuchen und der Server bekommt nicht mitgeteilt welcher es ist. Und es gibt keine Methode, die mit absoluter Sicherheit in der Lage wäre, allein aus Daten eine Codierung zu erkennen. Weiterhin ist zu beachten, dass nicht alle Browser dieses Attribut korrekt auswerten und sich daran halten. Man kann sich also nicht darauf verlassen, weswegen man es im Prinzip auch gleich weglassen kann.

Ein weiteres Problem entsteht, wenn Sie eine Codierung für einen begrenzten Zeichensatz verwendet haben, beispielsweise ISO-8859-1, und der Anwender Zeichen eingegeben hat, die mit dieser Codierung nicht darstellbar sind. Auch für diesen Fall gibt es keine einheitliche Regel, wie der Browser zu verfahren hat. Einige Browser senden statt dieser Zeichen eine Numerische Zeichenreferenz. Das Problem dabei ist, dass serverseitig nicht unterschieden werden kann, ob ein & nun vom Anwender eingegeben wurde oder ob der Browser es für die Umschreibung eines Zeichen eingefügt hat. Mit UTF-8 hingegen sind Sie auf der sicheren Seite.

Nachdem nun die eingegebenen Zeichen vom Browser in eine bestimmte Codierung gebracht wurden, werden sie nun noch URL-codiert. Auf dem Server muss also zunächst eine URL-Decodierung erfolgen. Als PHP-Anwender muss man selbst nichts unternehmen, denn in Servervariablen ($_POST, $_GET) stehen bereits die decodierten Daten.

Beispiel: POST
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Beispiel-Formular</title> </head> <body> <form method="post" action=""> <input type="text" name="foo" value="Umlaut-Ärger"> <input type="submit"> </form> </body> </html>
Oben sehen Sie ein Formular und unten den vom Browser erzeugten (etwas gekürzten) Request, wenn man es absendet.
POST /test.php HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 ... Content-Type: application/x-www-form-urlencoded Content-Length: 21 foo=Umlaut-%C3%84rger
Das Ä von „Umlaut-Ärger“ wurde UTF-8-codiert (C3 84) und anschließend URL-codiert (%C3 %84).

[Bearbeiten] URL, inklusive GET

In einer URL gibt es zwei Bereiche, in denen Daten transportiert werden können. Das ist zum einen der Path und zum anderen der Querystring.

Ein Querystring ist entweder in Links vorhanden oder wird vom Browser bei einem Formular mit method="GET" erstellt. Für ein Formular gilt grundsätzlich auch das im obigen Abschnitt zu POST gesagte. Aus der href-Angabe in Links wird hingegen (zumindest von Firefox (3.6) und IE8) direkt die Request-URL gebildet, ohne eine URL-Codierung vorzunehmen.

Interessant wird die Geschichte erst, wenn es keine Webseite mit einer definierten Codierungsangabe gibt, in der ein anklickbarer Link steht, also wenn man zum Beispiel eine URL händisch in die Adress-Zeile des Browsers eingibt, sie aus einer Textdatei kopiert oder ein externes Programm dem Browser eine URL übergibt. In dem Fall hat der Browser keine Response und deren Zeichencodierungsangabe vorliegen, er muss sich also bei einer Default-Konfiguration bedienen. Hier verhalten sich die Browser durchaus unterschiedlich, und verwenden teilweise auch verschiedene Codierungen für Path und Querystring. Doch das ist ein Thema für den Abschnitt Zeichencodierung - Browser.

[Bearbeiten] Tools

Um lediglich die Angaben zur Zeichenkodierung zu prüfen, kann man den W3C Internationalization Checker verwenden. Die kompletten HTTP-Header lassen sich einerseits mit einen Netzwerksniffer à la Wireshark ansehen, doch leichter zu bedienen sind Erweiterungen (Plugins) für Browser.

Meine Werkzeuge
Namensräume

Varianten
Aktionen
Übersicht
Hilfe
SELFHTML
Diverses
Werkzeuge
Flattr
Soziale Netzwerke