Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 28 additions & 19 deletions src/main/java/com/pusher/client/util/Base64.java
Original file line number Diff line number Diff line change
@@ -1,39 +1,48 @@
package com.pusher.client.util;

// copied from: https://stackoverflow.com/a/4265472/501940
import static java.util.Arrays.fill;

// copied from: https://stackoverflow.com/a/4265472/501940 and improved (naming, char validation)
public class Base64 {

private final static char[] ALPHABET =
private final static char[] CHAR_INDEX_TABLE =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();

private static int[] toInt = new int[128];
private static int[] charToIndexSparseMappingArray = new int[128];

static {
for (int i = 0; i < ALPHABET.length; i++) {
toInt[ALPHABET[i]] = i;
fill(charToIndexSparseMappingArray, -1);
for (int i = 0; i < CHAR_INDEX_TABLE.length; i++) {
charToIndexSparseMappingArray[CHAR_INDEX_TABLE[i]] = i;
}
}

private static int toInt(char character) {
int retVal = charToIndexSparseMappingArray[character];
if (retVal == -1) throw new IllegalArgumentException("invalid char: " + character);
return retVal;
}

public static byte[] decode(String base64String) {
int delta = base64String.endsWith("==") ? 2 : base64String.endsWith("=") ? 1 : 0;
byte[] buffer = new byte[base64String.length() * 3 / 4 - delta];
int paddingSize = base64String.endsWith("==") ? 2 : base64String.endsWith("=") ? 1 : 0;
byte[] retVal = new byte[base64String.length() * 3 / 4 - paddingSize];
int mask = 0xFF;
int index = 0;
for (int i = 0; i < base64String.length(); i += 4) {
int c0 = toInt[base64String.charAt(i)];
int c1 = toInt[base64String.charAt(i + 1)];
buffer[index++] = (byte) (((c0 << 2) | (c1 >> 4)) & mask);
if (index >= buffer.length) {
return buffer;
int c0 = toInt(base64String.charAt(i));
int c1 = toInt(base64String.charAt(i + 1));
retVal[index++] = (byte) (((c0 << 2) | (c1 >> 4)) & mask);
if (index >= retVal.length) {
return retVal;
}
int c2 = toInt[base64String.charAt(i + 2)];
buffer[index++] = (byte) (((c1 << 4) | (c2 >> 2)) & mask);
if (index >= buffer.length) {
return buffer;
int c2 = toInt(base64String.charAt(i + 2));
retVal[index++] = (byte) (((c1 << 4) | (c2 >> 2)) & mask);
if (index >= retVal.length) {
return retVal;
}
int c3 = toInt[base64String.charAt(i + 3)];
buffer[index++] = (byte) (((c2 << 6) | c3) & mask);
int c3 = toInt(base64String.charAt(i + 3));
retVal[index++] = (byte) (((c2 << 6) | c3) & mask);
}
return buffer;
return retVal;
}
}
27 changes: 27 additions & 0 deletions src/test/java/com/pusher/client/util/Base64Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.pusher.client.util;

import static com.google.common.truth.Truth.assertThat;

import org.junit.Test;

public class Base64Test {

@Test
public void decodeValidChars() {
String validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
assertThat(Base64.decode(validChars)).isNotEmpty();
}

// https://en.wikipedia.org/wiki/Base64#URL_applications
@Test(expected = IllegalArgumentException.class)
public void failDecodingMinusChar() {
Base64.decode("-");
}

// https://en.wikipedia.org/wiki/Base64#URL_applications
@Test(expected = IllegalArgumentException.class)
public void failDecodingUnderscoreChar() {
Base64.decode("_");
}

}