@Test public void failsDecodeUncompletedString() { String wrongEncoded = "%D0%9F%3F%D1%80%23%D0%B8%20%D0%B2%D1%96%D1%8"; thrown.expect(IllegalArgumentException.class); thrown.expectMessage(String.format("Malformed string '%s' at index %d", wrongEncoded, 42)); decode(wrongEncoded, HOST); }
public static String decode(String str, int component) { if (str == null) { throw new IllegalArgumentException("Decoded string is null"); } int length = str.length(); if (length < 3 && str.indexOf('%') >= 0) { throw new IllegalArgumentException("Malformed string: " + str); } int p = str.lastIndexOf('%'); if (p > 0 && p > (length - 3)) { throw new IllegalArgumentException("Malformed string '" + str + "' at index " + p); } p = 0; StringBuilder sb = new StringBuilder(); NoSyncByteArrayOutputStream buff = null; while (p < length) { char c = str.charAt(p); switch (c) { case '%': if (p + 2 > length) { throw new IllegalArgumentException("Malformed string '" + str + "' at index " + p); } if (buff == null) { buff = new NoSyncByteArrayOutputStream(4); } else { buff.reset(); } p = percentDecode(str, p, buff); byte[] bytes = buff.toByteArray(); if (bytes.length == 1 && (bytes[0] & 0xFF) < 128) { sb.append((char)bytes[0]); } else { sb.append(UTF8.decode(ByteBuffer.wrap(bytes))); } break; case '+': sb.append(' '); p++; break; default: sb.append(c); p++; break; } } return sb.toString(); }
UriComponent { public static String decode(String str, int component) { if (str == null) { throw new IllegalArgumentException("Decoded string is null"); } int length = str.length(); if (length < 3 && str.indexOf('%') >= 0) { throw new IllegalArgumentException("Malformed string: " + str); } int p = str.lastIndexOf('%'); if (p > 0 && p > (length - 3)) { throw new IllegalArgumentException("Malformed string '" + str + "' at index " + p); } p = 0; StringBuilder sb = new StringBuilder(); NoSyncByteArrayOutputStream buff = null; while (p < length) { char c = str.charAt(p); switch (c) { case '%': if (p + 2 > length) { throw new IllegalArgumentException("Malformed string '" + str + "' at index " + p); } if (buff == null) { buff = new NoSyncByteArrayOutputStream(4); } else { buff.reset(); } p = percentDecode(str, p, buff); byte[] bytes = buff.toByteArray(); if (bytes.length == 1 && (bytes[0] & 0xFF) < 128) { sb.append((char)bytes[0]); } else { sb.append(UTF8.decode(ByteBuffer.wrap(bytes))); } break; case '+': sb.append(' '); p++; break; default: sb.append(c); p++; break; } } return sb.toString(); } }
UriComponent { public static String decode(String str, int component) { if (str == null) { throw new IllegalArgumentException("Decoded string is null"); } int length = str.length(); if (length < 3 && str.indexOf('%') >= 0) { throw new IllegalArgumentException("Malformed string: " + str); } int p = str.lastIndexOf('%'); if (p > 0 && p > (length - 3)) { throw new IllegalArgumentException("Malformed string '" + str + "' at index " + p); } p = 0; StringBuilder sb = new StringBuilder(); NoSyncByteArrayOutputStream buff = null; while (p < length) { char c = str.charAt(p); switch (c) { case '%': if (p + 2 > length) { throw new IllegalArgumentException("Malformed string '" + str + "' at index " + p); } if (buff == null) { buff = new NoSyncByteArrayOutputStream(4); } else { buff.reset(); } p = percentDecode(str, p, buff); byte[] bytes = buff.toByteArray(); if (bytes.length == 1 && (bytes[0] & 0xFF) < 128) { sb.append((char)bytes[0]); } else { sb.append(UTF8.decode(ByteBuffer.wrap(bytes))); } break; case '+': sb.append(' '); p++; break; default: sb.append(c); p++; break; } } return sb.toString(); } private  UriComponent(); }
UriComponent { public static String decode(String str, int component) { if (str == null) { throw new IllegalArgumentException("Decoded string is null"); } int length = str.length(); if (length < 3 && str.indexOf('%') >= 0) { throw new IllegalArgumentException("Malformed string: " + str); } int p = str.lastIndexOf('%'); if (p > 0 && p > (length - 3)) { throw new IllegalArgumentException("Malformed string '" + str + "' at index " + p); } p = 0; StringBuilder sb = new StringBuilder(); NoSyncByteArrayOutputStream buff = null; while (p < length) { char c = str.charAt(p); switch (c) { case '%': if (p + 2 > length) { throw new IllegalArgumentException("Malformed string '" + str + "' at index " + p); } if (buff == null) { buff = new NoSyncByteArrayOutputStream(4); } else { buff.reset(); } p = percentDecode(str, p, buff); byte[] bytes = buff.toByteArray(); if (bytes.length == 1 && (bytes[0] & 0xFF) < 128) { sb.append((char)bytes[0]); } else { sb.append(UTF8.decode(ByteBuffer.wrap(bytes))); } break; case '+': sb.append(' '); p++; break; default: sb.append(c); p++; break; } } return sb.toString(); } private  UriComponent(); static URI normalize(URI uri); static String encode(String str, int component, boolean containsUriParams); static String validateUriComponent(String str, int component, boolean containsUriParams); static boolean isUriComponentContainsValidCharacters(int component, String str); static String recognizeEncode(String str, int component, boolean containsUriParams); static String decode(String str, int component); static boolean checkHexCharacters(String s, int p); static List<PathSegment> parsePathSegments(String path, boolean decode); static MultivaluedMap<String, String> parseQueryString(String rawQuery, boolean decode); static URI resolve(URI baseUri, URI resolvingUri); }
UriComponent { public static String decode(String str, int component) { if (str == null) { throw new IllegalArgumentException("Decoded string is null"); } int length = str.length(); if (length < 3 && str.indexOf('%') >= 0) { throw new IllegalArgumentException("Malformed string: " + str); } int p = str.lastIndexOf('%'); if (p > 0 && p > (length - 3)) { throw new IllegalArgumentException("Malformed string '" + str + "' at index " + p); } p = 0; StringBuilder sb = new StringBuilder(); NoSyncByteArrayOutputStream buff = null; while (p < length) { char c = str.charAt(p); switch (c) { case '%': if (p + 2 > length) { throw new IllegalArgumentException("Malformed string '" + str + "' at index " + p); } if (buff == null) { buff = new NoSyncByteArrayOutputStream(4); } else { buff.reset(); } p = percentDecode(str, p, buff); byte[] bytes = buff.toByteArray(); if (bytes.length == 1 && (bytes[0] & 0xFF) < 128) { sb.append((char)bytes[0]); } else { sb.append(UTF8.decode(ByteBuffer.wrap(bytes))); } break; case '+': sb.append(' '); p++; break; default: sb.append(c); p++; break; } } return sb.toString(); } private  UriComponent(); static URI normalize(URI uri); static String encode(String str, int component, boolean containsUriParams); static String validateUriComponent(String str, int component, boolean containsUriParams); static boolean isUriComponentContainsValidCharacters(int component, String str); static String recognizeEncode(String str, int component, boolean containsUriParams); static String decode(String str, int component); static boolean checkHexCharacters(String s, int p); static List<PathSegment> parsePathSegments(String path, boolean decode); static MultivaluedMap<String, String> parseQueryString(String rawQuery, boolean decode); static URI resolve(URI baseUri, URI resolvingUri); static final int SCHEME; static final int USER_INFO; static final int HOST; static final int PORT; static final int PATH_SEGMENT; static final int PATH; static final int QUERY; static final int FRAGMENT; static final int SSP; static final int MATRIX_PARAM; static final int QUERY_STRING; static final String PERCENT; }