ubuntuusers.de

[Python] Bottle, Unicode und Html

Status: Gelöst | Ubuntu-Version: Ubuntu 11.04 (Natty Narwhal)
Antworten |

Glocke

Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

Hallo,

vorneweg: ich verwendet bottle 0.8.4 via easy_install.

Momentan schreibe ich an einer pythonbasierten Webanwendung. Sie basiert aus bottle und elixir. Jedoch habe ich ein kleines aber unfeines Problem mit Umlauten: Strings werden in der Datenbank als Unicodes gehandelt und bei Bedarf mittels SimpleTemplate Engine - die bottle mitbringt - ausgegeben. Dabei treten häufig Unicode Dekodierungsprobleme wegen der Umlaute auf. Da ich auf diese nicht verzichten kann, habe ich die Umlaute datenbankseitig durch die äquivalenten Html Substitute (ü etc.) ersetzt und beim Einfügen in die Templates ein ! ergänzt, dass diese korrekt interpretiert werden (also {{!foo}} etc.)

Ich finde die Möglichkeit nicht so prickelnd, da auch Benutzereingaben Umlaute enthalten können, in der Datenbank gespeichert werden und in Templates ausgegeben werden sollen. Allerdings bringt das aus meiner Sicht Sicherheitsprobleme mit sich, da durch {{!foo}} diverse Html-Tags nicht escapet werden. Sehe ich das richtig? Welche Möglichkeiten habe ich hier?

LG Glocke

/EDIT: und auf einmal gehts problemlos ohne den Umweg O_o

/EDIT2: aber nur mit dem internen Server, mit apache (mod_wsgi) erscheint immer die tolle Meldung "ascii" ..

TypeError: sequence of byte string values expected, value of type int found

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Die Datenbank verwaltet keine Unicodes, sondern Bytes. Die Daten liegen also in einer speziellen Codierung vor. Da man innerhalb eines Pythonscriptes sinnvoller Weise mit Unicode arbeiten will, müssen diese Daten also beim Lesen (schreiben) entsprechend decodiert (encodiert) werden. Viele DB-Module bieten von Hause aus an, das automatisch zu wandeln, sofern man ihnen das Encoding angibt. Du müsstest also mal bestätigen, dass Du das auf diese Weise erledigst und innerhalb von Bottle (bzw. der Elixir-Klassen) wirklich Unicode-Objekte vorliegen hast.

Dann stellt sich die Frage, wo genau diese Probleme auftreten? In der Templating-Engine? Wenn ja, scheint diese nicht mit Unicode umgehen zu können (wage ich mal zu bezweifeln) oder man muss ihr ein Encoding übergeben. Wenn das per default auf ASCII eingestellt ist, kracht es natürlich bei Umlauten.

Wie ich grad gesehen habe, scheint diese aber per default auf utf-8 zu stehen! Aber vielleicht ist das eine andere Version und bei Deiner ist das noch anders?

Du musst also mal prüfen, ob die Daten korrekt aus der DB kommen (Testausgabe auf der Shell) und ob man bei korrekten Unicode-Strings diese im Template darstellen kann (einfach mal einen statischen Unicodestring an ein Template schicken!).

Glocke

(Themenstarter)
Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

Lysander schrieb:

Die Datenbank verwaltet keine Unicodes, sondern Bytes. Die Daten liegen also in einer speziellen Codierung vor. Da man innerhalb eines Pythonscriptes sinnvoller Weise mit Unicode arbeiten will, müssen diese Daten also beim Lesen (schreiben) entsprechend decodiert (encodiert) werden. Viele DB-Module bieten von Hause aus an, das automatisch zu wandeln, sofern man ihnen das Encoding angibt. Du müsstest also mal bestätigen, dass Du das auf diese Weise erledigst und innerhalb von Bottle (bzw. der Elixir-Klassen) wirklich Unicode-Objekte vorliegen hast.

Sorry für die Formulierung. Ich meinte natürlich, dass Unicode-Objekte vorliegen.

Lysander schrieb:

Dann stellt sich die Frage, wo genau diese Probleme auftreten? In der Templating-Engine? Wenn ja, scheint diese nicht mit Unicode umgehen zu können (wage ich mal zu bezweifeln) oder man muss ihr ein Encoding übergeben. Wenn das per default auf ASCII eingestellt ist, kracht es natürlich bei Umlauten.

Das muss ich noch genauer rausfinden.

Lysander schrieb:

Wie ich grad gesehen habe, scheint diese aber per default auf utf-8 zu stehen! Aber vielleicht ist das eine andere Version und bei Deiner ist das noch anders?

Ist bei mir auch auf utf-8.

Lysander schrieb:

Du musst also mal prüfen, ob die Daten korrekt aus der DB kommen (Testausgabe auf der Shell) und ob man bei korrekten Unicode-Strings diese im Template darstellen kann (einfach mal einen statischen Unicodestring an ein Template schicken!).

Die Strings sind Unicode. Soviel steht fest.

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Schick doch mal schnell einen statischen Unicodestring an ein Tenplate! Das kann man ja flott testen.

Glocke

(Themenstarter)
Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

Lysander schrieb:

Schick doch mal schnell einen statischen Unicodestring an ein Tenplate! Das kann man ja flott testen.

Das funktioniert. Ich habe gerade herausgefunden, WO der Fehler auftritt: Ich verwende Exceptions um in der Logik eingetretene Ereignisse zurückzugeben. Man denke sich z.B. das Speichern eines Datensatzes. Tritt dabei ein Fehler auf wird eine Exception (mit einer Unicode Message geraiset). Und exakt diese Unicode Message ist beim Einfügen in's Template die Fehlerursache. Ich überlege gerade die Exception-Geschichte zu verzichten (klingt, jetzt wo ich so drüber nachdenke umständlich).

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Glocke schrieb:

Lysander schrieb:

Schick doch mal schnell einen statischen Unicodestring an ein Tenplate! Das kann man ja flott testen.

Das funktioniert.

Ok.

Ich habe gerade herausgefunden, WO der Fehler auftritt: Ich verwende Exceptions um in der Logik eingetretene Ereignisse zurückzugeben. Man denke sich z.B. das Speichern eines Datensatzes. Tritt dabei ein Fehler auf wird eine Exception (mit einer Unicode Message geraiset). Und exakt diese Unicode Message ist beim Einfügen in's Template die Fehlerursache. Ich überlege gerade die Exception-Geschichte zu verzichten (klingt, jetzt wo ich so drüber nachdenke umständlich).

Also tritt der Fehler beim callen der Excpetion auf? Da hätte uns ein Stacktrace schnell auf die richtige Spur gebracht!

Generell ist es keine gute Idee Exceptions an Templates und damit an die Ausgabe des Frontends weiterzuleiten. Ggf. kann so etwas Hinweise auf einen möglichen Exploit liefern.

Glocke

(Themenstarter)
Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

Das seltsame ist, dass

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from bottle import route, run, template

@route('/test')
def test():
    try:
        raise Exception(u'Hällo Wörld')
    except Exception as e:
        return template(u'{{foo}}', foo=unicode(e))

run()

jedoch funktioniert...

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Du solltest einem Template natürlich niemals ein Objekt übergeben, bei dem nicht klar ist, wie es serialisiert wird. Vermutlich wird beim Generieren des Templates irgend wann mal die __str__-Methode von Exception aufgerufen - und dann wird eben ASCII als Basis angenommen. Das kann bei anderen Objekten auch der Fall sein! Probiere das doch mal mit einer Liste von Unicodestrings, die auch Umlaute enthalten. Ich wette da wird der gleiche Fehler auftreten.

Kleines Beispiel:

1
2
3
4
5
6
7
8
9
In [8]: ex = Exception(u"Hallöle")

In [9]: str(ex)
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
/home/nelson/<ipython-input-9-c277618b0823> in <module>()
----> 1 str(ex)

UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 4: ordinal not in range(128)

Bei Deinem hier gegebenen Beispiel übergibst Du dem Template einen Unicodestring und alles ist ok. Insofern ist das Verhalten absolut ok.

Glocke

(Themenstarter)
Avatar von Glocke

Anmeldungsdatum:
1. März 2009

Beiträge: 880

Wohnort: Thüringen

–- CUT –-

Ich hab jetzt in mühevoller Kleinarbeit die gesamte Exception Geschichte für die Meldungen entfernt - die Messages werden nun per Return zurückgegeben. Nun geht alles fehlerfrei!

Danke für deine Mühe, Lysander 😉

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Glocke schrieb:

Ich hab jetzt in mühevoller Kleinarbeit die gesamte Exception Geschichte für die Meldungen entfernt - die Messages werden nun per Return zurückgegeben. Nun geht alles fehlerfrei!

Hm... wie ich schon schrieb sollte man das eigentlich nicht ausgeben! Der gangbare Weg wäre es hier, das ganze in ein Log zu schreiben und auf der Seite nur einen Fehler auszugeben. Macht diese Seite hier garantiert auch - immerhin sieht man ja ab und an mal eine Fehlerseite; aber eben keine detaillierte Exceptionmeldung.

Antworten |