fix query parameter charset encoding

This commit is contained in:
Jörg Prante 2019-09-17 20:24:23 +02:00
parent 64ae0f60bf
commit f3173094e5
7 changed files with 57 additions and 14 deletions

View file

@ -1,6 +1,6 @@
group = org.xbib
name = net
version = 2.0.1
version = 2.0.2
# test
junit.version = 5.5.1
@ -9,5 +9,3 @@ jackson.version = 2.9.9
# doc
asciidoclet.version = 1.5.4
org.gradle.warning.mode = all

View file

@ -11,6 +11,8 @@ import java.nio.charset.UnmappableCharacterException;
/**
* Decodes percent-encoded strings.
*
* This class is not thread-safe.
*/
public class PercentDecoder {

View file

@ -13,6 +13,8 @@ import java.util.BitSet;
*
* This is typically done when encoding components of URLs. See {@link PercentEncoders} for pre-configured
* PercentEncoder instances.
*
* This class is not thread-safe.
*/
public class PercentEncoder {

View file

@ -1,6 +1,9 @@
package org.xbib.net;
import java.nio.charset.Charset;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.MalformedInputException;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnmappableCharacterException;
import java.util.ArrayList;
import java.util.List;
@ -25,8 +28,27 @@ public class QueryParameters extends ArrayList<Pair<String, String>> {
}
public QueryParameters(int max) {
this(StandardCharsets.UTF_8, max);
}
public QueryParameters(Charset charset) {
this(charset, 1024);
}
public QueryParameters(Charset charset, int max) {
this(new PercentDecoder(charset.newDecoder()
.onUnmappableCharacter(CodingErrorAction.REPLACE)
.onMalformedInput(CodingErrorAction.REPLACE)), max);
}
public QueryParameters(PercentDecoder percentDecoder) {
this(percentDecoder, 1024);
}
public QueryParameters(PercentDecoder percentDecoder, int max) {
this.percentDecoder = percentDecoder;
this.max = max;
this.percentDecoder = new PercentDecoder();
}
public List<String> get(String key) {
@ -51,14 +73,20 @@ public class QueryParameters extends ArrayList<Pair<String, String>> {
return o instanceof QueryParameters && super.equals(o);
}
public QueryParameters addPercentEncodedBody(String body) throws MalformedInputException, UnmappableCharacterException {
public QueryParameters addPercentEncodedBody(String body) {
String s = body;
while (s != null) {
Pair<String, String> pairs = indexOf(AMPERSAND_CHAR, s);
Pair<String, String> pair = indexOf(EQUAL_CHAR, pairs.getFirst());
if (!isNullOrEmpty(pair.getFirst())) {
add(percentDecoder.decode(pair.getFirst()),
percentDecoder.decode(pair.getSecond()));
try {
add(percentDecoder.decode(pair.getFirst()),
percentDecoder.decode(pair.getSecond()));
} catch (MalformedInputException e) {
// never thrown
} catch (UnmappableCharacterException e) {
// never thrown
}
}
s = pairs.getSecond();
}

View file

@ -11,6 +11,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.MalformedInputException;
import java.nio.charset.StandardCharsets;
@ -825,7 +826,7 @@ public class URL implements Comparable<URL> {
private PercentDecoder percentDecoder;
private final QueryParameters queryParams;
private QueryParameters queryParams;
private final List<PathSegment> pathSegments;
@ -854,22 +855,24 @@ public class URL implements Comparable<URL> {
private boolean fatalResolveErrorsEnabled;
private Builder() {
this.queryParams = new QueryParameters();
this.pathSegments = new ArrayList<>();
charset(StandardCharsets.UTF_8, CodingErrorAction.REPLACE);
}
/**
* Set the character set of the URL. Default is UTF-8.
* @param charset the chaarcter set
* @param charset the character set
* @param codingErrorAction the coding error action
* @return this builder
*/
public Builder charset(Charset charset, CodingErrorAction codingErrorAction) {
this.charset = charset;
this.codingErrorAction = codingErrorAction;
this.regNameEncoder = PercentEncoders.getRegNameEncoder(charset);
this.percentDecoder = new PercentDecoder(charset.newDecoder()
.onUnmappableCharacter(codingErrorAction));
CharsetDecoder charsetDecoder = charset.newDecoder()
.onUnmappableCharacter(codingErrorAction);
this.percentDecoder = new PercentDecoder(charsetDecoder);
this.queryParams = new QueryParameters(percentDecoder);
return this;
}

View file

@ -434,6 +434,16 @@ class URLParserTest {
assertEquals("http://library.fes.de/library/journals/de-part/das-rote-blättla/index.html", url.toString());
}
@Test
void testPathQueryFragmentFromPath(){
URL url = URL.builder()
.path("/a/b?c=d#e")
.build();
assertEquals("/a/b", url.getPath());
assertEquals("c=d", url.getQuery());
assertEquals("e", url.getFragment());
}
private void assertUrlCompatibility(String url) throws Exception {
String s = URL.from(url).toExternalForm();
assertEquals(s, URL.from(s).toExternalForm());

View file

@ -13,7 +13,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
class ParseBodyTest {
@Test
void testSimpleParse() throws MalformedInputException, UnmappableCharacterException {
void testSimpleParse() {
QueryParameters queryParameters = new QueryParameters();
String body = "a=b&c=d&e=f";
queryParameters.addPercentEncodedBody(body);
@ -23,7 +23,7 @@ class ParseBodyTest {
}
@Test
void testManyParse() throws MalformedInputException, UnmappableCharacterException {
void testManyParse() {
QueryParameters queryParameters = new QueryParameters(100);
List<String> list = new ArrayList<>();
for (int i = 0; i < 200; i++) {