Skip to content

Commit 4fed3e8

Browse files
authored
Merge pull request #237 from pusher/base64Validation
Add Base64 char validation
2 parents 540ff2d + 1d43fdb commit 4fed3e8

File tree

2 files changed

+55
-19
lines changed

2 files changed

+55
-19
lines changed
Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,48 @@
11
package com.pusher.client.util;
22

3-
// copied from: https://stackoverflow.com/a/4265472/501940
3+
import static java.util.Arrays.fill;
4+
5+
// copied from: https://stackoverflow.com/a/4265472/501940 and improved (naming, char validation)
46
public class Base64 {
57

6-
private final static char[] ALPHABET =
8+
private final static char[] CHAR_INDEX_TABLE =
79
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
810

9-
private static int[] toInt = new int[128];
11+
private static int[] charToIndexSparseMappingArray = new int[128];
1012

1113
static {
12-
for (int i = 0; i < ALPHABET.length; i++) {
13-
toInt[ALPHABET[i]] = i;
14+
fill(charToIndexSparseMappingArray, -1);
15+
for (int i = 0; i < CHAR_INDEX_TABLE.length; i++) {
16+
charToIndexSparseMappingArray[CHAR_INDEX_TABLE[i]] = i;
1417
}
1518
}
1619

20+
private static int toInt(char character) {
21+
int retVal = charToIndexSparseMappingArray[character];
22+
if (retVal == -1) throw new IllegalArgumentException("invalid char: " + character);
23+
return retVal;
24+
}
25+
1726
public static byte[] decode(String base64String) {
18-
int delta = base64String.endsWith("==") ? 2 : base64String.endsWith("=") ? 1 : 0;
19-
byte[] buffer = new byte[base64String.length() * 3 / 4 - delta];
27+
int paddingSize = base64String.endsWith("==") ? 2 : base64String.endsWith("=") ? 1 : 0;
28+
byte[] retVal = new byte[base64String.length() * 3 / 4 - paddingSize];
2029
int mask = 0xFF;
2130
int index = 0;
2231
for (int i = 0; i < base64String.length(); i += 4) {
23-
int c0 = toInt[base64String.charAt(i)];
24-
int c1 = toInt[base64String.charAt(i + 1)];
25-
buffer[index++] = (byte) (((c0 << 2) | (c1 >> 4)) & mask);
26-
if (index >= buffer.length) {
27-
return buffer;
32+
int c0 = toInt(base64String.charAt(i));
33+
int c1 = toInt(base64String.charAt(i + 1));
34+
retVal[index++] = (byte) (((c0 << 2) | (c1 >> 4)) & mask);
35+
if (index >= retVal.length) {
36+
return retVal;
2837
}
29-
int c2 = toInt[base64String.charAt(i + 2)];
30-
buffer[index++] = (byte) (((c1 << 4) | (c2 >> 2)) & mask);
31-
if (index >= buffer.length) {
32-
return buffer;
38+
int c2 = toInt(base64String.charAt(i + 2));
39+
retVal[index++] = (byte) (((c1 << 4) | (c2 >> 2)) & mask);
40+
if (index >= retVal.length) {
41+
return retVal;
3342
}
34-
int c3 = toInt[base64String.charAt(i + 3)];
35-
buffer[index++] = (byte) (((c2 << 6) | c3) & mask);
43+
int c3 = toInt(base64String.charAt(i + 3));
44+
retVal[index++] = (byte) (((c2 << 6) | c3) & mask);
3645
}
37-
return buffer;
46+
return retVal;
3847
}
3948
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.pusher.client.util;
2+
3+
import static com.google.common.truth.Truth.assertThat;
4+
5+
import org.junit.Test;
6+
7+
public class Base64Test {
8+
9+
@Test
10+
public void decodeValidChars() {
11+
String validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
12+
assertThat(Base64.decode(validChars)).isNotEmpty();
13+
}
14+
15+
// https://en.wikipedia.org/wiki/Base64#URL_applications
16+
@Test(expected = IllegalArgumentException.class)
17+
public void failDecodingMinusChar() {
18+
Base64.decode("-");
19+
}
20+
21+
// https://en.wikipedia.org/wiki/Base64#URL_applications
22+
@Test(expected = IllegalArgumentException.class)
23+
public void failDecodingUnderscoreChar() {
24+
Base64.decode("_");
25+
}
26+
27+
}

0 commit comments

Comments
 (0)