/*
* Copyright 2013 Skynav, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY SKYNAV, INC. AND ITS CONTRIBUTORS “AS IS” AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL SKYNAV, INC. OR ITS CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.skynav.ttv.verifier.util;
import java.nio.ByteBuffer;
public class Base64 {
private static final byte[] decodeMap;
static {
decodeMap = makeDecodeMap();
}
private static byte[] getDecodeMap() {
return decodeMap;
}
private static final byte PAD = 127;
private static byte[] makeDecodeMap() {
byte[] map = new byte[128];
for (int i = 0; i < 128; ++i)
map[i] = -1;
for (int i = 'A'; i <= 'Z'; ++i)
map[i] = (byte) (i - 'A');
for (int i = 'a'; i <= 'z'; ++i)
map[i] = (byte) (i - 'a' + 26);
for (int i = '0'; i <= '9'; ++i)
map[i] = (byte) (i - '0' + 52);
map['+'] = 62;
map['/'] = 63;
map['='] = PAD;
return map;
}
public static byte[] decode(String data) {
final ByteBuffer bb = ByteBuffer.allocate(data.length());
final byte[] map = getDecodeMap();
final byte[] grp = new byte[4];
for (int i = 0, n = data.length(); i < n; ) {
int k = 0;
while (k < 4) {
if (i < n) {
char c = data.charAt(i++);
if (Characters.isXMLSpace(c))
continue;
else if (c < 128) {
byte bits = map[c];
if (bits == -1) {
throw new IllegalArgumentException("Character '" + Characters.maybeEscapeAsNCRef(c) + "' is not in Base64 alphabet.");
} else if ((bits == PAD) && (k == 0)) {
throw new IllegalArgumentException("Padding not permitted in first position of group.");
} else if ((bits == PAD) && (k == 1)) {
throw new IllegalArgumentException("Padding not permitted in second position of group.");
} else {
grp[k++] = bits;
}
} else {
throw new IllegalArgumentException("Character '" + Characters.maybeEscapeAsNCRef(c) + "' is not in Base64 alphabet.");
}
} else if (k > 0) {
throw new IllegalArgumentException("Input data underflow, got " + k + " of four (4) Base64 alphabet characters.");
} else {
break;
}
}
if (k == 4) {
bb.put((byte)((grp[0] << 2) | (grp[1] >> 4)));
if (grp[2] != PAD)
bb.put((byte)((grp[1] << 4) | (grp[2] >> 2)));
if (grp[3] != PAD)
bb.put((byte)((grp[2] << 6) | grp[3]));
}
}
byte[] out = new byte[bb.position()];
bb.rewind();
bb.get(out);
return out;
}
public static boolean isBase64(String data) {
try {
decode(data);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
}