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    }