Skip to content
This repository was archived by the owner on Feb 8, 2023. It is now read-only.

Commit 9e305c9

Browse files
author
Thomas Lutz
committed
Fix #14: Decoding fails when two encoded characters appear one after another
1 parent c887dec commit 9e305c9

File tree

2 files changed

+29
-18
lines changed

2 files changed

+29
-18
lines changed

src/main/java/com/github/jscookie/javacookie/Cookies.java

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -296,27 +296,31 @@ private String encode( String decoded, Set<Integer> exceptions ) {
296296
String character = new String( Character.toChars( codePoint ) );
297297
CharArrayWriter hexSequence = new CharArrayWriter();
298298
byte[] bytes = character.getBytes( UTF_8 );
299-
for ( int bytesIndex = 0; bytesIndex < bytes.length; bytesIndex++ ) {
300-
char left = Character.forDigit( bytes[ bytesIndex ] >> 4 & 0xF, 16 );
301-
char right = Character.forDigit( bytes[ bytesIndex ] & 0xF, 16 );
299+
for (byte aByte : bytes) {
300+
char left = Character.forDigit(aByte >> 4 & 0xF, 16);
301+
char right = Character.forDigit(aByte & 0xF, 16);
302302
hexSequence
303-
.append( '%' )
304-
.append( left )
305-
.append( right );
303+
.append('%')
304+
.append(left)
305+
.append(right);
306306
}
307-
String target = character.toString();
308307
String sequence = hexSequence.toString().toUpperCase();
309-
encoded = encoded.replace( target, sequence );
308+
encoded = encoded.replace(character, sequence );
310309
} catch ( UnsupportedEncodingException e ) {
311310
e.printStackTrace();
312311
}
313312
}
314313
return encoded;
315314
}
316315

317-
private String decode( String encoded ) {
316+
private String decode(String encoded) {
317+
// Decode characters with 3 bytes first, then with 1 byte to fix https://github.com/js-cookie/java-cookie/issues/14
318+
return decode( decode( encoded, 3 ), 1 );
319+
}
320+
321+
private String decode( String encoded, Integer bytesPerCharacter ) {
318322
String decoded = encoded;
319-
Pattern pattern = Pattern.compile( "(%[0-9A-Z]{2})+" );
323+
Pattern pattern = Pattern.compile( "(%[0-9A-Z]{2}){" + bytesPerCharacter + "}" );
320324
Matcher matcher = pattern.matcher( encoded );
321325
while ( matcher.find() ) {
322326
String encodedChar = matcher.group();
@@ -392,14 +396,13 @@ private String decodeValue( String encodedValue, String decodedName ) {
392396
private Map<String, String> getCookies( String cookieHeader ) {
393397
Map<String, String> result = new HashMap<String, String>();
394398
String[] cookies = cookieHeader.split( "; " );
395-
for ( int i = 0; i < cookies.length; i++ ) {
396-
String cookie = cookies[ i ];
397-
String encodedName = cookie.split( "=" )[ 0 ];
398-
String decodedName = decode( encodedName );
399-
400-
String encodedValue = cookie.substring( cookie.indexOf( '=' ) + 1, cookie.length() );
401-
String decodedValue = decodeValue( encodedValue, decodedName );
402-
result.put( decodedName, decodedValue );
399+
for (String cookie : cookies) {
400+
String encodedName = cookie.split("=")[0];
401+
String decodedName = decode(encodedName);
402+
403+
String encodedValue = cookie.substring(cookie.indexOf('=') + 1);
404+
String decodedValue = decodeValue(encodedValue, decodedName);
405+
result.put(decodedName, decodedValue);
403406
}
404407
return result;
405408
}

src/test/java/com/github/jscookie/javacookie/test/unit/CookiesDecodingTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,12 @@ public void character_with_3_bytes() {
3434
String expected = "京";
3535
Assert.assertEquals( expected, actual );
3636
}
37+
38+
@Test
39+
public void two_encoded_characters() {
40+
Mockito.when(request.getHeader("cookie")).thenReturn("c=New%20York%2C%20NY");
41+
String actual = cookies.get("c");
42+
String expected = "New York, NY";
43+
Assert.assertEquals(expected, actual);
44+
}
3745
}

0 commit comments

Comments
 (0)