enhancement
critical
major
minor
minor
minor
#25035
StructuredTextControl has problems with special characters in image filenames
The StructuredTextControl has at least the following issues with images that have special characters in their names:
- Characters that are URL-encoded cause the image to be deleted immediately after upload. This is caused by the code that deletes images that are no longer in use. In this process, the name of each image is compared to the names of the images currently in use. However, the names of the images in use are URL-encoded. As a result, " Koala - 128px.jpeg " is compared to " Koala%20-%20128px.jpeg." This means the entry is not found, and the image is deleted as "no longer in use."
- Even if this is fixed, such images will still not be displayed. The URL for the image would then be Koala%2520-%2520128px.jpeg. The percent signs in the encoded name have thus been re-encoded. The name is therefore double-encoded. This is likely why the image cannot be found.
- Characters not included in ISO-8859-1 cause a problem when the response is sent to the client after the image is uploaded:
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)
The problem here is that while the StructuredTextControl correctly specifies that the response should be encoded in UTF-8, the implementation of `javax.servlet.ServletOutputStream ` used by Jetty apparently ignores the character encoding and uses ISO-8859-1 instead. (To understand the source code: Java characters are internally encoded in UTF-16. This corresponds to ISO-8859-1 as long as the high byte is not set.)
{{{#!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);
}
}
}}}
Improvement
- Before checking whether images can be deleted, the image names are now decoded.
- Decoding must not be performed only after com.top_logic.layout.wysiwyg.ui.StructuredTextControl.linkImageSource(String, Element), as suggested in the patch, because the encoded string is already set as the src value in the image at that point, whereas the decoded version must also be used there. Therefore, decoding is now performed in com.top_logic.layout.wysiwyg.ui.StructuredTextControl.getImageID(String, String).
- In `com.top_logic.layout.wysiwyg.ui.StructuredTextControl.sendResponse(DisplayContext, FileItemBinaryData, String)`, the `PrintWriter` is now used because it can handle strings, whereas the `OutputStream` only processes binary data and then ignores the encoding.
Test
In the documentation: Inserting images with special characters, e.g., ÄÖÜ, €, spaces, etc. The image must remain intact even after saving.
Related Tickets
Noticed in the context of #19000