001    /*
002        
003        $Id: Base64.java,v 1.2 2003/05/08 10:34:22 culdesac Exp $
004        
005    */
006    
007    package sharpster.common;
008    
009    public class Base64 {
010        public static String encode(byte[] raw) {
011            StringBuffer encoded = new StringBuffer();
012            for (int i = 0; i < raw.length; i += 3) {
013                encoded.append(encodeBlock(raw, i));
014            }
015            return encoded.toString();
016        }
017    
018        protected static char[] encodeBlock(byte[] raw, int offset) {
019            int block = 0;
020            int slack = raw.length - offset - 1;
021            int end = (slack >= 2) ? 2 : slack;
022            for (int i = 0; i <= end; i++) {
023                byte b = raw[offset + i];
024                int neuter = (b < 0) ? b + 256 : b;
025                block += neuter << (8 * (2 - i));
026            }
027            char[] base64 = new char[4];
028            for (int i = 0; i < 4; i++) {
029                int sixbit = (block >>> (6 * (3 - i))) & 0x3f;
030                base64[i] = getChar(sixbit);
031            }
032            if (slack < 1) base64[2] = '=';
033            if (slack < 2) base64[3] = '=';
034            return base64;
035        }
036        
037        protected static char getChar(int sixBit) {
038            if (sixBit >= 0 && sixBit <= 25)
039                return (char)('A' + sixBit);
040            if (sixBit >= 26 && sixBit <= 51)
041                return (char)('a' + (sixBit - 26));
042            if (sixBit >= 52 && sixBit <= 61)
043                return (char)('0' + (sixBit - 52));
044            if (sixBit == 62) return '+';
045            if (sixBit == 63) return '/';
046            return '?';
047        }
048        
049        public static byte[] decode(String base64) {
050            int pad = 0;
051            for (int i = base64.length() - 1; base64.charAt(i) == '='; i--)
052                pad++;
053            int length = base64.length() * 6 / 8 - pad;
054            byte[] raw = new byte[length];
055            int rawIndex = 0;
056            for (int i = 0; i < base64.length(); i += 4) {
057                int block = (getValue(base64.charAt(i)) << 18)
058                    + (getValue(base64.charAt(i + 1)) << 12)
059                    + (getValue(base64.charAt(i + 2)) << 6)
060              + (getValue(base64.charAt(i + 3)));
061                for (int j = 0; j < 3 && rawIndex + j < raw.length; j++)
062                    raw[rawIndex + j] = (byte)((block >> (8 * (2 - j))) & 0xff);
063                rawIndex += 3;
064            }
065            return raw;
066        }
067        
068        protected static int getValue(char c) {
069            if (c >= 'A' && c <= 'Z') return c - 'A';
070            if (c >= 'a' && c <= 'z') return c - 'a' + 26;
071            if (c >= '0' && c <= '9') return c - '0' + 52;
072            if (c == '+') return 62;
073            if (c == '/') return 63;
074        if (c == '=') return 0;
075        return -1;
076      }
077    }