001 package biweekly.util;
002
003 /**
004 * Encodes and decodes data into base64.
005 * @author <a href="http://stackoverflow.com/users/518568/georgek">GeorgeK</a>
006 * @see <a
007 * href="http://stackoverflow.com/a/4265472/13379">http://stackoverflow.com/a/4265472/13379</a>
008 */
009 public class Base64 {
010 private static final char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
011 private static final int[] toInt = new int[128];
012 static {
013 for (int i = 0; i < ALPHABET.length; i++) {
014 toInt[ALPHABET[i]] = i;
015 }
016 }
017
018 /**
019 * Translates the specified byte array into Base64 string.
020 * @param buf the byte array
021 * @return the translated Base64 string
022 */
023 public static String encode(byte[] buf) {
024 int size = buf.length;
025 char[] ar = new char[((size + 2) / 3) * 4];
026 int a = 0;
027 int i = 0;
028 while (i < size) {
029 byte b0 = buf[i++];
030 byte b1 = (i < size) ? buf[i++] : 0;
031 byte b2 = (i < size) ? buf[i++] : 0;
032
033 int mask = 0x3F;
034 ar[a++] = ALPHABET[(b0 >> 2) & mask];
035 ar[a++] = ALPHABET[((b0 << 4) | ((b1 & 0xFF) >> 4)) & mask];
036 ar[a++] = ALPHABET[((b1 << 2) | ((b2 & 0xFF) >> 6)) & mask];
037 ar[a++] = ALPHABET[b2 & mask];
038 }
039 switch (size % 3) {
040 case 1:
041 ar[--a] = '=';
042 case 2:
043 ar[--a] = '=';
044 }
045 return new String(ar);
046 }
047
048 /**
049 * Translates the specified Base64 string into a byte array.
050 * @param s the Base64 string
051 * @return the byte array
052 */
053 public static byte[] decode(String s) {
054 int delta = s.endsWith("==") ? 2 : s.endsWith("=") ? 1 : 0;
055 byte[] buffer = new byte[s.length() * 3 / 4 - delta];
056 int mask = 0xFF;
057 int index = 0;
058 for (int i = 0; i < s.length(); i += 4) {
059 int c0 = toInt[s.charAt(i)];
060 int c1 = toInt[s.charAt(i + 1)];
061 buffer[index++] = (byte) (((c0 << 2) | (c1 >> 4)) & mask);
062 if (index >= buffer.length) {
063 return buffer;
064 }
065 int c2 = toInt[s.charAt(i + 2)];
066 buffer[index++] = (byte) (((c1 << 4) | (c2 >> 2)) & mask);
067 if (index >= buffer.length) {
068 return buffer;
069 }
070 int c3 = toInt[s.charAt(i + 3)];
071 buffer[index++] = (byte) (((c2 << 6) | c3) & mask);
072 }
073 return buffer;
074 }
075
076 private Base64() {
077 //hide
078 }
079 }