update to gradle 5.6, more resilient percent decoding
This commit is contained in:
parent
f3173094e5
commit
339327ee81
11 changed files with 59 additions and 55 deletions
|
@ -1,6 +1,6 @@
|
|||
group = org.xbib
|
||||
name = net
|
||||
version = 2.0.2
|
||||
version = 2.0.3
|
||||
|
||||
# test
|
||||
junit.version = 5.5.1
|
||||
|
|
5
gradle/wrapper/gradle-wrapper.properties
vendored
5
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,5 @@
|
|||
#Wed Aug 07 23:28:18 CEST 2019
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.3.1-all.zip
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
6
gradlew
vendored
6
gradlew
vendored
|
@ -7,7 +7,7 @@
|
|||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -125,8 +125,8 @@ if $darwin; then
|
|||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
|
2
gradlew.bat
vendored
2
gradlew.bat
vendored
|
@ -5,7 +5,7 @@
|
|||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem http://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
|
|
@ -34,7 +34,9 @@ public class PercentDecoder {
|
|||
private ByteBuffer encodedBuf;
|
||||
|
||||
public PercentDecoder() {
|
||||
this(StandardCharsets.UTF_8.newDecoder().onMalformedInput(CodingErrorAction.REPORT));
|
||||
this(StandardCharsets.UTF_8.newDecoder()
|
||||
.onUnmappableCharacter(CodingErrorAction.REPORT)
|
||||
.onMalformedInput(CodingErrorAction.REPORT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,8 +54,7 @@ public class PercentDecoder {
|
|||
* @param initialEncodedByteBufSize Initial size of buffer that holds encoded bytes
|
||||
* @param decodedCharBufSize Size of buffer that encoded bytes are decoded into
|
||||
*/
|
||||
public PercentDecoder(CharsetDecoder charsetDecoder, int initialEncodedByteBufSize,
|
||||
int decodedCharBufSize) {
|
||||
public PercentDecoder(CharsetDecoder charsetDecoder, int initialEncodedByteBufSize, int decodedCharBufSize) {
|
||||
this.outputBuf = new StringBuilder();
|
||||
this.encodedBuf = ByteBuffer.allocate(initialEncodedByteBufSize);
|
||||
this.decodedCharBuf = CharBuffer.allocate(decodedCharBufSize);
|
||||
|
@ -85,9 +86,7 @@ public class PercentDecoder {
|
|||
continue;
|
||||
}
|
||||
if (i + 2 >= input.length()) {
|
||||
throw new IllegalArgumentException("could not percent decode <"
|
||||
+ input
|
||||
+ ">: incomplete %-pair at position " + i);
|
||||
throw new MalformedInputException(i);
|
||||
}
|
||||
if (encodedBuf.remaining() == 0) {
|
||||
ByteBuffer largerBuf = ByteBuffer.allocate(encodedBuf.capacity() * 2);
|
||||
|
@ -97,21 +96,18 @@ public class PercentDecoder {
|
|||
}
|
||||
int c1 = input.charAt(++i);
|
||||
int c2 = input.charAt(++i);
|
||||
encodedBuf.put(decode((char) c1, (char) c2));
|
||||
byte b1 = (byte) decode((char) c1);
|
||||
byte b2 = (byte) decode((char) c2);
|
||||
/*if (b1 == -1 || b2 == -1) {
|
||||
throw new MalformedInputException(i);
|
||||
}*/
|
||||
byte b = (byte) ((b1 & 0xf) << 4 | (b2 & 0xf));
|
||||
encodedBuf.put(b);
|
||||
}
|
||||
handleEncodedBytes();
|
||||
return outputBuf.toString();
|
||||
}
|
||||
|
||||
private static byte decode(char c1, char c2) {
|
||||
byte b1 = (byte) decode(c1);
|
||||
byte b2 = (byte) decode(c2);
|
||||
if (b1 == -1 || b2 == -1) {
|
||||
throw new IllegalArgumentException("invalid %-tuple <%" + c1 + c2 + ">");
|
||||
}
|
||||
return (byte) ((b1 & 0xf) << 4 | (b2 & 0xf));
|
||||
}
|
||||
|
||||
private static int decode(char c) {
|
||||
return (c >= '0' && c <= '9') ? c - '0' :
|
||||
(c >= 'A' && c <= 'F') ? c - 'A' + 10 :
|
||||
|
|
|
@ -11,6 +11,8 @@ import java.util.stream.Collectors;
|
|||
|
||||
/**
|
||||
* Query parameter list, of limited size. Default is 1024 pairs.
|
||||
*
|
||||
* This class is not thread-safe.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class QueryParameters extends ArrayList<Pair<String, String>> {
|
||||
|
@ -41,7 +43,6 @@ public class QueryParameters extends ArrayList<Pair<String, String>> {
|
|||
.onMalformedInput(CodingErrorAction.REPLACE)), max);
|
||||
}
|
||||
|
||||
|
||||
public QueryParameters(PercentDecoder percentDecoder) {
|
||||
this(percentDecoder, 1024);
|
||||
}
|
||||
|
@ -82,10 +83,8 @@ public class QueryParameters extends ArrayList<Pair<String, String>> {
|
|||
try {
|
||||
add(percentDecoder.decode(pair.getFirst()),
|
||||
percentDecoder.decode(pair.getSecond()));
|
||||
} catch (MalformedInputException e) {
|
||||
// never thrown
|
||||
} catch (UnmappableCharacterException e) {
|
||||
// never thrown
|
||||
} catch (MalformedInputException | UnmappableCharacterException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
s = pairs.getSecond();
|
||||
|
|
|
@ -870,6 +870,7 @@ public class URL implements Comparable<URL> {
|
|||
this.codingErrorAction = codingErrorAction;
|
||||
this.regNameEncoder = PercentEncoders.getRegNameEncoder(charset);
|
||||
CharsetDecoder charsetDecoder = charset.newDecoder()
|
||||
.onMalformedInput(codingErrorAction)
|
||||
.onUnmappableCharacter(codingErrorAction);
|
||||
this.percentDecoder = new PercentDecoder(charsetDecoder);
|
||||
this.queryParams = new QueryParameters(percentDecoder);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.xbib.net;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.charset.MalformedInputException;
|
||||
|
@ -22,7 +23,7 @@ class PercentDecoderTest {
|
|||
|
||||
private static final int CODE_POINT_IN_BMP = 1;
|
||||
|
||||
private PercentDecoder decoder = new PercentDecoder(StandardCharsets.UTF_8.newDecoder());
|
||||
private PercentDecoder decoder = new PercentDecoder();
|
||||
|
||||
@Test
|
||||
void testDecodesWithoutPercents() throws Exception {
|
||||
|
@ -35,33 +36,24 @@ class PercentDecoderTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testIncompletePercentPairNoNumbers() throws Exception {
|
||||
try {
|
||||
void testIncompletePercentPairNoNumbers() {
|
||||
Assertions.assertThrows(MalformedInputException.class, () ->{
|
||||
decoder.decode("%");
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("could not percent decode <%>: incomplete %-pair at position 0", e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIncompletePercentPairOneNumber() throws Exception {
|
||||
try {
|
||||
void testIncompletePercentPairOneNumber() {
|
||||
Assertions.assertThrows(MalformedInputException.class, () ->{
|
||||
decoder.decode("%2");
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("could not percent decode <%2>: incomplete %-pair at position 0", e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidHex() throws Exception {
|
||||
try {
|
||||
void testInvalidHex() {
|
||||
Assertions.assertThrows(MalformedInputException.class, () ->{
|
||||
decoder.decode("%xz");
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("invalid %-tuple <%xz>", e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.xbib.net;
|
|||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CodingErrorAction;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
|
@ -444,6 +445,25 @@ class URLParserTest {
|
|||
assertEquals("e", url.getFragment());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUrlCharsetReplacementAndReport() {
|
||||
Charset charset = StandardCharsets.UTF_8;
|
||||
URL url = URL.builder()
|
||||
.charset(charset, CodingErrorAction.REPLACE)
|
||||
.path("/bla%PDblabla?a=b")
|
||||
.build();
|
||||
QueryParameters queryParameters = url.getQueryParams();
|
||||
// %EF%BF%B = 0xFFFD UNICODE REPLACEMENT CHARACTER
|
||||
assertEquals("/bla%EF%BF%BDblabla", url.getPath());
|
||||
assertEquals("[a=b]", queryParameters.toString());
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> {
|
||||
URL.builder()
|
||||
.charset(charset, CodingErrorAction.REPORT)
|
||||
.path("/bla%PDblabla?a=b")
|
||||
.build();
|
||||
});
|
||||
}
|
||||
|
||||
private void assertUrlCompatibility(String url) throws Exception {
|
||||
String s = URL.from(url).toExternalForm();
|
||||
assertEquals(s, URL.from(s).toExternalForm());
|
||||
|
|
|
@ -26,7 +26,7 @@ class URLTest {
|
|||
if (test.failure) {
|
||||
try {
|
||||
URL.base(base).resolve(input);
|
||||
fail();
|
||||
fail("base = " + base + " input = " + input);
|
||||
} catch (Exception e) {
|
||||
// pass
|
||||
}
|
||||
|
|
|
@ -2064,8 +2064,7 @@
|
|||
"port": "",
|
||||
"pathname": "/foo%2zbar",
|
||||
"search": "",
|
||||
"hash": "",
|
||||
"failure": true
|
||||
"hash": ""
|
||||
},
|
||||
{
|
||||
"input": "http://example.com/foo%2©zbar",
|
||||
|
@ -2080,8 +2079,7 @@
|
|||
"port": "",
|
||||
"pathname": "/foo%2%C3%82%C2%A9zbar",
|
||||
"search": "",
|
||||
"hash": "",
|
||||
"failure": true
|
||||
"hash": ""
|
||||
},
|
||||
{
|
||||
"input": "http://example.com/foo%41%7a",
|
||||
|
@ -4607,8 +4605,7 @@
|
|||
"port": "",
|
||||
"pathname": "%1G",
|
||||
"search": "",
|
||||
"hash": "",
|
||||
"failure": true
|
||||
"hash": ""
|
||||
},
|
||||
"# Hosts and percent-encoding",
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue