[TYPO3-german] TYPO3 und Charset-Chaos

Stephan Schuler Stephan.Schuler at netlogix.de
Fri May 14 19:38:47 CEST 2010


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hallo Peter.


Die betreffenden Felder der Datenbank (Tabele sys_template, Spalte "config" uvm.) waren lange Zeit BLOB. Das bedeutet unter anderem, dass MySQL eben *keine* Charsetkonviertierungen irgend einer Art durchführt sondern -- viel schlimmer eigentlich -- beim Dump den base64-encodierten String dieser Zeichenkette erzeugt (sofern man nicht hex2text vorgibt).
Irgend wann im vergangenen Jahr wurde dann das Feld von BLOB zu TEXT geändert. Den genauen Zeitpunkt habe ich nicht mehr im Kopf. Ableiten lässt sich das aber schon an den aktuellen SVN-Versionen von 4.1 und 4.2, 4.1 hat diese Änderung nämlich nicht erfahren.

Wenn das Übertragungscharset ein anderes ist als das Charset der Zieldaten führt MySQL eine automatische Konvertierung durch. Dann steht zwar unter Umständen Müll in der Datenbank, weil aber auf dem Rückweg die umgekehrte Konvertierung durchgeführt wird ist das ab und an nicht weiter tragisch.
Wenn nun Binarydaten gespeichert werden sollen findet trotz unpassender Charsets (Transfaircharset im Vergleich zur datenbankspezifischen Kolation, die konkrete BLOB-Spalte hat ja kein Charset) keine Konvertierung statt. Noch ist auch das kein Problem, weil auch auf dem Rückweg keine Änderung stattfindet.
Leider liegen die Daten in Strigattributen jetzt in einem anderen Charset in der Datenbank als die Daten in BLOB-Attributen. Je nachdem von welchem Charset man ausgeht sind die einen oder die anderen verkehrt. Häufig würde ich sagen die BLOB-Daten sind zwar aus Verbindungssicht korrekt aber aus Datenbanksicht falsch. Das ist aber Haarspalterei und hier nicht weiter wichtig.

Der Fehler fliegt auf, wenn BLOB zu TEXT konvertiert wird.

Gehen wir mal beispielhaft von Latin-Verbindungen und UTF8-Datenbanken aus um die "wenns" ein wenig zu reduzieren. Ich rede mal ausschließlich von der Tabelle sys_templates, und zwar von den Spalten title (varchar, denke ich) und config (anfangs BLOB, jetzt TEXT).
Zunächst spricht der Webserver LATIN mit dem MySQL-Server, MySQL speichert die Daten UTF-8. PHP denkt, dass die Daten schon UTF-8 an die Datenbank gehen.
Schreiboperation: UTF-8 durch die Latin-Verbindug (von der PHP nichts weiß sondern von UTF-8 ausgeht). MySQL codiert den title "von Latin nach UTF-8". Weil der schon UTF-8 war liegt der jetzt doppelt-UTF-8 in der Datenbank. "config" wird ohne Konvertierung als Binary übertragen. Zwar gehen MySQL und PHP von unterschiedlichen Charsets aus, das ist aber beiden egal weil s ja angeblich Binarydaten sind.
Leseoperation: Die Datenbank dreht den title "von UTF-8 nach Latin" (doppelt-UTF-8 nach normal UTF-8), am PHP-Prozess kommt durch die Latin-Verbindung trotzdem UTF-8 an. Binary wird nicht verändert. Die Daten stimmen also in beiden Fällen.
Jetzt wird das config-Attribut der Tabelle von BLOB zu TEXT definiert.
Die nachfolgende Leseoperation geht wie bisher von Latin-Verbindungen aus, MySQL von UTF-8-Daten. Es werden sowohl die title-Spalte konvertiert (aus doppel-UTF-8 wird wieder UTF-8), aus der config-Spalte wird jetzt aber von UTF-8 wirklich Latin. Beim PHP-Prozess kommen jetzt für die selbe Tabelle unterschiedliche Charsets an, und von beiden glaubt er er würde UTF-8 bekommen.

Das muss jetzt nicht zwingend deine Situation gewesen sein, Peter. Wenn bei dir die Verbindung schon von Anfang an UTF-8 war speichert die Datenbank vielleicht nicht UTF-8 im für den config-BLOB und doppel-UTF-8 für den title sondern Latin für den Config-BLOB und UTF-8 für den title. Die genauen Umstände lassen sich im Nachhinein oft nur schwer ermitteln.


Das bringt euch jetzt zwar der Lösung eures Problems nicht näher, erklärt aber, warum bei einer Charsetkonvertierung einige Daten mitkommen und andere nicht.


Grüße,



Stephan Schuler
Web-Entwickler

Telefon: +49 (911) 539909 - 0
E-Mail: Stephan.Schuler at netlogix.de

- --
netlogix GmbH & Co. KG
Systemhaus | Trainingscenter | Medienagentur
Andernacher Straße 53 | 90411 Nürnberg
Telefon: +49 (911) 539909 - 0 | Fax: +49 (911) 539909 - 99
E-Mail: mailto:info at netlogix.de | Internet: http://www.netlogix.de/

netlogix GmbH & Co. KG ist eingetragen am Amtsgericht Nürnberg (HRA 13338)
Persönlich haftende Gesellschafterin: netlogix Verwaltungs GmbH (HRB 20634)
Umsatzsteuer-Identifikationsnummer: DE 233472254
Geschäftsführer: Stefan Buchta, Matthias Schmidt

________________________________________


Von: typo3-german-bounces at lists.typo3.org [typo3-german-bounces at lists.typo3.org] im Auftrag von Peter Linzenkirchner [liste at lisardo.de]
Gesendet: Freitag, 14. Mai 2010 18:58
An: German TYPO3 Userlist
Betreff: Re: [TYPO3-german] TYPO3 und Charset-Chaos

Hallo Raphael,

> Die Datenbank (MySQL 5)ist komplett auf utf8 eingestellt
> (character_set_client, character_set_connection,
> character_set_database) und im Installtool steht '[BE][forceCharset]
> = utf-8' aktiviert.

Das ist richtig. Entscheidend ist m. W. nicht nur die Kollation der
Datenbank sondern auch die Kollation der Datenbankverbindung.
Standardmäßig ist die Kollation der Datenbankverbindung eben nicht
automatisch UTF-8, sondern erst dann, wenn man diese mit set names
utf-8 erzwingt. Das ist kein Problem von TYOPO3 sondern ein Problem
von PHP und MySQL und wird erst seit MySQL 5 wirklich zum Problem.
Deshalb wurde in den Versionen von TYPO3 > 4.0 auch die Option set
names eingeführt.

Das ganze wird noch dadurch kompliziert, dass nicht nur beim Schreiben
durch TYPO3 die Kollation der DB-Verbindung beachtet werden muss,
sondern auch beim Erstellen des Dump. Wenn du den Export z. B. mit
einer neuen Version von phpMyAdmin vornimmst, so wird per Default der
Dump mit set names utf-8 erstellt, was MySQL veranlasst, UTF-8-Dateien
zu liefern. Heisst, der Dump von phpMyAdmin ist in jedem Fall UTF-8,
ausser du stellst die Datenbankverbindung in phpMyAdmin absichtlich um
auf latin.

Mit anderen Worten: MySQL konvertiert selbstständig die Daten, die es
bekommt und liefert, und zwar abhängig von der Kollation der
Datenbankverbindung.

> Was mich jetzt allerdings brennend interessiert:
> a) wie werden die Eingaben aus dem Backend tatsächlich kodiert, wenn
> forceCharset auf utf-8 gesetzt ist und setDBinit keine Anweisung
> enthält?

Das hängt m. W. von der Konfiguration von MySQL und/oder PHP ab, kann
also auf jedem System anders aussehen. Aber m. W. werden in der Regel
dann utf-8 Daten über eine latin-DB-Verbindung gesendet, was dazu
führt, dass in der DB die utf-8-Zeichen in latin gespeichert werden.
Das kann man schön sehen, wenn man mit phpMyAdmin drauf geht und dort
fehlerhafte Zeichen sieht, während TYPO3 korrektes utf-8 ausliefert.

> Nachdem ich nach zahlreichen Tests definitiv ausschliessen kann,
> dass der Dump fehlerhaft ist, konnte ich den Verursacher
> mittlerweile auf TYPO3 eingrenzen.


Ist er das? Welchen Zeichensatz hast du im Dump tatsächlich? Öffnen
mit einem Texteditor und nachschauen ist die einzige Möglichkeit das
rauszufinden. Je nachdem, mit welcher Datenbankverbindung du den Dump
erstellst, erhältst du Latin oder utf-8 im Dump, und zwar unabhängig
davon, welche Daten in der Datenbank drin sind ... Auf der sicheren
Seite ist man dann, wenn man bei _jeder_ Datenbankverbindung set names
= utf8 verwendet, also auch dann, wenn der Dump erstellt und wieder
eingespielt wird. Wenn du in einen Dump von phpMyAdmin reinschaust,
wirst du ganz oben entsprechende Komentarzeilen finden, die die DB-
Verbindung einstellen:

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

> b) wie kann ich die verwurstete Datenbank wieder in korrektes UTF-8
> zurückcodieren?

Normalerweise kein allzugroßes Problem, allerdings nur wenn die Daten
nicht gemischt wurden - also wenn TYPO3 z. B. eine Zeit lang mit und
ohne set names gearbeitet hat. Es gibt ja nur zwei Möglichkeiten: der
Dump ist in utf-8 oder er ist in latin. Ensprechend kann man vorgehen:

- - dump in utf-8:
Beim Zurückspielen in die DB darauf achten, dass die Verbindung auf
set names = utf-8 steht. Danach in TYPO3 die beiden Einstellungen von
oben vornehmen, dann müsste es klappen. So habe ich schon eine ganze
Reihe von Installation von Latin auf utf-8 rübergezogen.

- - dump in latin:
Konvertieren in utf-8 und dann wie oben.

Achtung: ein Problem waren bei mir Umlaute in den TypoScript-
Templates, die leider dazu geführt haben, dass ab den Umlauten das
restliche TypoScript gefehlt hat. Warum weiss ich nicht - bei mir kein
großes Problem, da ich das TS eh extern halte. Wenn es jemand weiss,
warum das passiert - bitte posten :-)

>
> Bin für jeden Vorschlag dankbar, da ich schon alleine für den Fall
> ein funktionierendes Backups meine Datenbanken reparieren muss!

wie gesagt: du musst beim Erstellen und beim Zurückspielen des Dumps
auf die korrekte Kollation achten.

Gruß
Peter



_______________________________________________
TYPO3-german mailing list
TYPO3-german at lists.typo3.org
http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german


-----BEGIN PGP SIGNATURE-----
Version: PGP Universal 3.0.0 (Build 2881)
Charset: Windows-1252

wpUDBQFL7Yqqpp0IwsibV8MBCBKHA/401NdW1P+SBBvXWWUdqLzFBJYRrEKBSAKr
dNsm0O74rIaMJc2weKFbYleat5eYsOXVCL1oJEUbfS4Txux2foN00J66XkByeJ9z
YlRHPDwuySWp/UfMrsc9KUSupu88eiVFIVMok3QR8xt2V53YsjJGvXSou+mLdzOT
sE/OuqrDFg==
=g2YK
-----END PGP SIGNATURE-----


More information about the TYPO3-german mailing list