diff --git a/core/src/main/java/hudson/Util.java b/core/src/main/java/hudson/Util.java index 73c3f03a9a703059a2c09ca8e6ff941714135407..76611efbd97a5416ead4aab03bab5a239102d40b 100644 --- a/core/src/main/java/hudson/Util.java +++ b/core/src/main/java/hudson/Util.java @@ -866,29 +866,50 @@ public class Util { CharBuffer buf = null; char c; for (int i = 0, m = s.length(); i < m; i++) { - c = s.charAt(i); - if (c > 122 || uriMap[c]) { + int codePoint = Character.codePointAt(s, i); + if((codePoint&0xffffff80)==0) { // 1 byte + c = s.charAt(i); + if (c > 122 || uriMap[c]) { + if (!escaped) { + out = new StringBuilder(i + (m - i) * 3); + out.append(s, 0, i); + enc = StandardCharsets.UTF_8.newEncoder(); + buf = CharBuffer.allocate(1); + escaped = true; + } + // 1 char -> UTF8 + buf.put(0, c); + buf.rewind(); + try { + ByteBuffer bytes = enc.encode(buf); + while (bytes.hasRemaining()) { + byte b = bytes.get(); + out.append('%'); + out.append(toDigit((b >> 4) & 0xF)); + out.append(toDigit(b & 0xF)); + } + } catch (CharacterCodingException ex) { + } + } else if (escaped) { + out.append(c); + } + } else { if (!escaped) { out = new StringBuilder(i + (m - i) * 3); out.append(s, 0, i); - enc = StandardCharsets.UTF_8.newEncoder(); - buf = CharBuffer.allocate(1); escaped = true; } - // 1 char -> UTF8 - buf.put(0,c); - buf.rewind(); - try { - ByteBuffer bytes = enc.encode(buf); - while (bytes.hasRemaining()) { - byte b = bytes.get(); - out.append('%'); - out.append(toDigit((b >> 4) & 0xF)); - out.append(toDigit(b & 0xF)); - } - } catch (CharacterCodingException ex) { } - } else if (escaped) { - out.append(c); + + byte[] bytes = new String(new int[] { codePoint }, 0, 1).getBytes(StandardCharsets.UTF_8); + for(int j=0;j> 4) & 0xF)); + out.append(toDigit(bytes[j] & 0xF)); + } + + if(Character.charCount(codePoint) > 1) { + i++; // we processed two characters + } } } return escaped ? out.toString() : s; diff --git a/core/src/test/java/hudson/UtilTest.java b/core/src/test/java/hudson/UtilTest.java index 0e8632e4f10a3389a964ff22d7e02a2de2e6b230..a346f889cf7c70fc7f25db854e779b649ccb56f4 100644 --- a/core/src/test/java/hudson/UtilTest.java +++ b/core/src/test/java/hudson/UtilTest.java @@ -158,6 +158,7 @@ public class UtilTest { " \"#%/:;<>?", "%20%22%23%25%2F%3A%3B%3C%3E%3F", "[\\]^`{|}~", "%5B%5C%5D%5E%60%7B%7C%7D%7E", "d\u00E9velopp\u00E9s", "d%C3%A9velopp%C3%A9s", + "Foo \uD800\uDF98 Foo", "Foo%20%F0%90%8E%98%20Foo" }; for (int i = 0; i < data.length; i += 2) { assertEquals("test " + i, data[i + 1], Util.rawEncode(data[i]));