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:24:52 UTC
[myfaces] branch 2.2.x 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 2.2.x
in repository https://gitbox.apache.org/repos/asf/myfaces.git
The following commit(s) were added to refs/heads/2.2.x by this push:
new 946b8c9 MYFACES-4294 Emoji characters are filtered in ajax requests
946b8c9 is described below
commit 946b8c9819c22c29a4dc21f77cc0f53e63838e54
Author: Thomas Andraschko <ta...@apache.org>
AuthorDate: Tue Jul 23 15:24:44 2019 +0200
MYFACES-4294 Emoji characters are filtered in ajax requests
---
.../util/IllegalXmlCharacterFilterWriter.java | 101 +++++++++++++++++----
.../context/PartialResponseWriterImplTest.java | 38 +++++++-
2 files changed, 116 insertions(+), 23 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 50953c8..3b6f5e1 100644
--- a/impl/src/main/java/org/apache/myfaces/util/IllegalXmlCharacterFilterWriter.java
+++ b/impl/src/main/java/org/apache/myfaces/util/IllegalXmlCharacterFilterWriter.java
@@ -31,7 +31,6 @@ import java.io.Writer;
*/
public class IllegalXmlCharacterFilterWriter extends FilterWriter
{
- private static final char[] EMPTY_CHAR_ARRAY = new char[0];
private static final char BLANK_CHAR = ' ';
public IllegalXmlCharacterFilterWriter(Writer out)
@@ -42,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);
}
@@ -71,26 +70,53 @@ public class IllegalXmlCharacterFilterWriter extends FilterWriter
return null;
}
- boolean containsInvalidChar = false;
- char[] encodedCharArray = EMPTY_CHAR_ARRAY;
-
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)
{
- if (!containsInvalidChar)
+ cNext = str.charAt(i + 1);
+ if (Character.isLowSurrogate(cNext))
{
- containsInvalidChar = true;
- encodedCharArray = str.toCharArray();
+ 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;
}
- encodedCharArray[i] = BLANK_CHAR;
}
}
- if (containsInvalidChar)
+ if (encoded != null)
{
- return String.valueOf(encodedCharArray);
+ return String.valueOf(encoded);
}
return str;
@@ -102,36 +128,73 @@ public class IllegalXmlCharacterFilterWriter extends FilterWriter
{
return null;
}
-
+
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 b876cbf..a505316 100644
--- a/impl/src/test/java/org/apache/myfaces/context/PartialResponseWriterImplTest.java
+++ b/impl/src/test/java/org/apache/myfaces/context/PartialResponseWriterImplTest.java
@@ -297,11 +297,11 @@ public class PartialResponseWriterImplTest extends AbstractJsfTestCase {
fail(e.toString());
}
}
-
+
public void testWriteIllegalXmlUnicodeCharacters() {
_writer = createTestProbe();
try {
- String illegalChars = " \u0001\u0002\u0003\u0004\u0005\u0006\u000B\f\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F \uD7FF\uDBFF\uDC00\uE000��";
+ String illegalChars = "\u0001\u0002\u0003\u0004\u0005\u0006\u000B\f\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F\uDBFF\uDC00";
String legalChars = "foo";
_writer.write(illegalChars + legalChars);
assertEquals("All illegal XML unicode characters should have been replaced by spaces", legalChars, _contentCollector.toString().trim());
@@ -314,7 +314,7 @@ public class PartialResponseWriterImplTest extends AbstractJsfTestCase {
public void testWriteTextIllegalXmlUnicodeCharacters() {
_writer = createTestProbe();
try {
- String illegalChars = " \u0001\u0002\u0003\u0004\u0005\u0006\u000B\f\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F \uD7FF\uDBFF\uDC00\uE000��";
+ String illegalChars = "\u0001\u0002\u0003\u0004\u0005\u0006\u000B\f\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F\uDBFF\uDC00";
String legalChars = "foo";
_writer.writeText(illegalChars + legalChars, null);
assertEquals("All illegal XML unicode characters should have been replaced by spaces", legalChars, _contentCollector.toString().trim());
@@ -327,7 +327,7 @@ public class PartialResponseWriterImplTest extends AbstractJsfTestCase {
public void testWriteAttributeIllegalXmlUnicodeCharacters() {
_writer = createTestProbe();
try {
- String illegalChars = " \u0001\u0002\u0003\u0004\u0005\u0006\u000B\f\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F \uD7FF\uDBFF\uDC00\uE000��";
+ String illegalChars = "\u0001\u0002\u0003\u0004\u0005\u0006\u000B\f\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F\uDBFF\uDC00";
String legalChars = "foo";
_writer.startElement(legalChars, null);
_writer.writeAttribute(legalChars, illegalChars + legalChars, null);
@@ -340,6 +340,36 @@ public class PartialResponseWriterImplTest extends AbstractJsfTestCase {
}
}
+ 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)
*