Verbesserung
Top-Thema
Detail
Wichtig
Detail
Detail
#25035
StructuredTextControl hat Probleme mit Sonderzeichen in Dateinamen von Bildern
Das StructuredTextControl hat mindestens folgende Probleme mit Bildern, die Sonderzeichen im Namen haben:
- Zeichen, die in URLs encodiert werden, führen dazu, dass das Bild direkt nach dem Upload gelöscht wird. Ursache ist der Code, der Bilder löscht, die nicht mehr verwendet werden. Dabei wird der Name jedes Bilder mit den Namen der verwendeten Bilder verglichen. Die Namen der verwendeten Bilder sind aber URL-Encodiert. Dadurch wird Koala - 128px.jpeg mit Koala%20-%20128px.jpeg verglichen. Dadurch wird der Eintrag nicht gefunden und das Bild wird als "nicht mehr verwendet" gelöscht.
- Wenn das gefixt wird, werden solche Bilder trotzdem nicht angezeigt. Die URL zu dem Bild lautet dann Koala%2520-%2520128px.jpeg. Die Prozent-Zeichen im encodierten Namen wurden also wieder encodiert. Der Name ist also doppelt encodiert. Vermutlich wird das Bild deswegen nicht gefunden.
- Zeichen, die nicht in ISO-8859-1 enthalten sind, führen zu einem Problem wenn nach dem Upload des Bildes die Antwort an den Client geschickt wird:
java.io.CharConversionException: Not an ISO 8859-1 character: € at javax.servlet.ServletOutputStream.print(ServletOutputStream.java:130) at com.top_logic.layout.wysiwyg.ui.StructuredTextControl.sendResponse(StructuredTextControl.java:735) at com.top_logic.layout.wysiwyg.ui.StructuredTextControl.uploadFile(StructuredTextControl.java:635)
Das Problem ist hierbei, dass das StructuredTextControl zwar korrekt setzt, das die Antwort in UTF-8 kodiert werden soll. Aber die vom Jetty verwendete Implementierung des javax.servlet.ServletOutputStream ignoriert das Character-Encoding anscheinend, und nutzt statt dessen ISO-8859-1. (Zum Verständnis des Quellcodes: Java Characters sind intern in UTF-16 kodiert. Das entspricht ISO-8859-1, solange das obere Byte nicht gesetzt ist.)
{{{#!java
public void print(String s) throws IOException {
if (s==null) s="null";
int len = s.length();
for (int i = 0; i < len; i++) {
char c = s.charAt (i);
//
// XXX NOTE: This is clearly incorrect for many strings,
// but is the only consistent approach within the current
// servlet framework. It must suffice until servlet output
// streams properly encode their output.
//
if ((c & 0xff00) != 0) { // high order byte must be zero
String errMsg = lStrings.getString("err.not_iso8859_1");
Object[] errArgs = new Object[1];
errArgs[0] = Character.valueOf(c);
errMsg = MessageFormat.format(errMsg, errArgs);
throw new CharConversionException(errMsg);
}
write (c);
}
}
}}}
Verbesserung
- Vor dem Vergleich, ob Bilder gelöscht werden können, werden die Bildnamen nun decodiert.
- Die Decodierung darf nicht wie im Patch vorgeschlagen erst nach com.top_logic.layout.wysiwyg.ui.StructuredTextControl.linkImageSource(String, Element) vorgenommen werden, da dort der Codierte String schon als src value im Bild gesetzt wird, wo aber ebenfalls die decodierte Variante genommen werden muss. Daher wird die Decodierung jetzt schon in com.top_logic.layout.wysiwyg.ui.StructuredTextControl.getImageID(String, String) vorgenommen.
- In com.top_logic.layout.wysiwyg.ui.StructuredTextControl.sendResponse(DisplayContext, FileItemBinaryData, String) wird jetzt der PrintWriter verwendet, da dieser mit Strings umgehen kann, während der OutputStream nur binäre Daten verarbeitet und dann die Codierung ignoriert.
Test
In der Dokumentation Bilder einfügen mit Sonderzeichen z.B. ÄÖÜ, €, Leerzeichen etc. Auch nach dem Speichern muss das Bild erhalten bleiben.
Verwandte Tickets
Aufgefallen im Rahmen von #19000