You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ta...@apache.org on 2019/07/23 13:13:17 UTC
[myfaces] branch master updated: MYFACES-4294 Emoji characters are
filtered in ajax requests
This is an automated email from the ASF dual-hosted git repository.
tandraschko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces.git
The following commit(s) were added to refs/heads/master by this push:
new c241590 MYFACES-4294 Emoji characters are filtered in ajax requests
c241590 is described below
commit c241590aadafdfc478b86143c87f4b1000270238
Author: Thomas Andraschko <ta...@apache.org>
AuthorDate: Tue Jul 23 15:13:09 2019 +0200
MYFACES-4294 Emoji characters are filtered in ajax requests
---
.../util/IllegalXmlCharacterFilterWriter.java | 94 +++++++++++++++++++---
.../context/PartialResponseWriterImplTest.java | 53 ++++++++++++
2 files changed, 134 insertions(+), 13 deletions(-)
diff --git a/impl/src/main/java/org/apache/myfaces/util/IllegalXmlCharacterFilterWriter.java b/impl/src/main/java/org/apache/myfaces/util/IllegalXmlCharacterFilterWriter.java
index fc9a22a..3b6f5e1 100644
--- a/impl/src/main/java/org/apache/myfaces/util/IllegalXmlCharacterFilterWriter.java
+++ b/impl/src/main/java/org/apache/myfaces/util/IllegalXmlCharacterFilterWriter.java
@@ -41,7 +41,7 @@ public class IllegalXmlCharacterFilterWriter extends FilterWriter
@Override
public void write(int c) throws IOException
{
- if (isInvalidChar((char) c))
+ if (isInvalidChar(c))
{
super.write((int) BLANK_CHAR);
}
@@ -69,18 +69,48 @@ public class IllegalXmlCharacterFilterWriter extends FilterWriter
{
return null;
}
-
- char[] encoded = null;
- for (int i = off; i < (off + len); i++)
+ int to = off + len;
+ boolean surrogateResolved = false;
+ char c;
+ int codePoint;
+ char cNext;
+
+ char[] encoded = null;
+ for (int i = off; i < to; i++)
{
- if (isInvalidChar(str.charAt(i)))
+ if (surrogateResolved == true)
+ {
+ surrogateResolved = false;
+ continue;
+ }
+
+ c = str.charAt(i);
+ codePoint = c;
+
+ if (Character.isHighSurrogate(c) && i + 1 < to)
+ {
+ cNext = str.charAt(i + 1);
+ if (Character.isLowSurrogate(cNext))
+ {
+ codePoint = Character.toCodePoint(c, cNext);
+ surrogateResolved = true;
+ }
+ }
+
+ // try to resolve surrogate, this is required e.g. for emojis
+ if ((!surrogateResolved && Character.isSurrogate(c)) || isInvalidChar(codePoint))
{
if (encoded == null)
{
encoded = str.toCharArray();
}
encoded[i] = BLANK_CHAR;
+
+ if (surrogateResolved)
+ {
+ encoded[i + 1] = BLANK_CHAR;
+ }
}
}
@@ -97,36 +127,74 @@ public class IllegalXmlCharacterFilterWriter extends FilterWriter
if (cbuf == null)
{
return null;
- }
+ }
- for (int i = off; i < (off + len); i++)
+ int to = off + len;
+
+ boolean surrogateResolved = false;
+ char c;
+ int codePoint;
+ char cNext;
+
+ for (int i = off; i < to; i++)
{
- if (isInvalidChar(cbuf[i]))
+ if (surrogateResolved == true)
+ {
+ surrogateResolved = false;
+ continue;
+ }
+
+ c = cbuf[i];
+ codePoint = c;
+
+ // try to resolve surrogate, this is required e.g. for emojis
+ if (Character.isHighSurrogate(c) && i + 1 < to)
+ {
+ cNext = cbuf[i + 1];
+ if (Character.isLowSurrogate(cNext))
+ {
+ codePoint = Character.toCodePoint(c, cNext);
+ surrogateResolved = true;
+ }
+ }
+
+ if ((!surrogateResolved && Character.isSurrogate(c)) || isInvalidChar(codePoint))
{
cbuf[i] = BLANK_CHAR;
+
+ if (surrogateResolved)
+ {
+ cbuf[i + 1] = BLANK_CHAR;
+ }
}
}
return cbuf;
}
- private static boolean isInvalidChar(char c)
+ private static boolean isInvalidChar(int codePoint)
{
- if (Character.isSurrogate(c))
+ if (codePoint == 1113088)
{
return true;
}
- if (c == '\u0009' || c == '\n' || c == '\r')
+
+ if (codePoint == 0x9 || codePoint == 0xA || codePoint == 0xD)
{
return false;
}
- if (c >= '\u0020' && c <= '\uD7FF')
+ if (codePoint >= 0x20 && codePoint <= 0xD7FF)
{
return false;
}
- if (c >= '\uE000' && c <= '\uFFFD')
+ if (codePoint >= 0xE000 && codePoint <= 0xFFFD)
{
return false;
}
+ if (codePoint >= 0x10000 && codePoint <= 0x10FFFF)
+ {
+ return false;
+ }
+
return true;
}
}
diff --git a/impl/src/test/java/org/apache/myfaces/context/PartialResponseWriterImplTest.java b/impl/src/test/java/org/apache/myfaces/context/PartialResponseWriterImplTest.java
index a9c4d2d..896047e 100644
--- a/impl/src/test/java/org/apache/myfaces/context/PartialResponseWriterImplTest.java
+++ b/impl/src/test/java/org/apache/myfaces/context/PartialResponseWriterImplTest.java
@@ -32,6 +32,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.myfaces.renderkit.html.HtmlResponseWriterImpl;
import org.apache.myfaces.test.base.AbstractJsfTestCase;
+import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
@@ -339,6 +340,36 @@ public class PartialResponseWriterImplTest extends AbstractJsfTestCase {
fail(e.toString());
}
}
+
+ public void testWriteSkipEmoji() {
+ _writer = createTestProbe();
+ try {
+ String input = "foo😀";
+ _writer.writeText(input, null);
+
+ String escaped = _contentCollector.toString();
+
+ assertEquals("All illegal XML unicode characters should have been replaced by spaces", input, escaped.trim());
+
+ } catch (IOException e) {
+ fail(e.toString());
+ }
+ }
+
+ public void testWriteSkipPictographs() {
+ _writer = createTestProbe();
+ try {
+ String input = "foo🏺";
+ _writer.writeText(input, null);
+
+ String escaped = _contentCollector.toString();
+
+ assertEquals("All illegal XML unicode characters should have been replaced by spaces", input, escaped.trim());
+
+ } catch (IOException e) {
+ fail(e.toString());
+ }
+ }
/**
* creates a new test probe (aka response writer)
@@ -349,4 +380,26 @@ public class PartialResponseWriterImplTest extends AbstractJsfTestCase {
return new PartialResponseWriterImpl(new HtmlResponseWriterImpl(_contentCollector, null, "UTF-8"));
}
+ /*
+ @Test
+ public void testPerf() throws IOException {
+
+ _contentCollector = new StringWriter();
+ _writer = createTestProbe();
+ for (int i = 0; i < 1000000; i++)
+ {
+ _writer.write("test");
+ }
+
+ long start = System.currentTimeMillis();
+ _contentCollector = new StringWriter();
+ _writer = createTestProbe();
+ for (int i = 0; i < 1000000; i++)
+ {
+ _writer.write("test");
+ }
+ long end = System.currentTimeMillis();
+ throw new RuntimeException((end - start) + "ms");
+ }
+ */
}