1:
37:
38:
39: package ;
40:
41: import ;
42:
43: import ;
44: import ;
45:
46:
50: public class Base64
51: {
52: private static final Logger log = Logger.getLogger(Base64.class.getName());
53:
54:
55: private static final int MAX_LINE_LENGTH = 76;
56:
57:
58: private static final byte NEW_LINE = (byte) '\n';
59:
60:
61: private static final byte EQUALS_SIGN = (byte) '=';
62:
63: private static final byte WHITE_SPACE_ENC = -5;
64:
65: private static final byte EQUALS_SIGN_ENC = -1;
66:
67:
68: private static final byte[] ALPHABET = {
69: (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
70: (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L',
71: (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R',
72: (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X',
73: (byte) 'Y', (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd',
74: (byte) 'e', (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
75: (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p',
76: (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v',
77: (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z', (byte) '0', (byte) '1',
78: (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
79: (byte) '8', (byte) '9', (byte) '+', (byte) '/'
80: };
81:
82:
86: private static final byte[] DECODABET = {
87: -9, -9, -9, -9, -9, -9, -9, -9, -9,
88: -5, -5,
89: -9, -9,
90: -5,
91: -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
92: -9, -9, -9, -9, -9,
93: -5,
94: -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
95: 62,
96: -9, -9, -9,
97: 63,
98: 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
99: -9, -9, -9,
100: -1,
101: -9, -9, -9,
102: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
103: 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
104: -9, -9, -9, -9, -9, -9,
105: 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
106: 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
107: -9, -9, -9, -9
108: };
109:
110:
111: private Base64()
112: {
113: super();
114: }
115:
116:
122: public static final String encode(final byte[] src)
123: {
124: return encode(src, 0, src.length, true);
125: }
126:
127:
135: public static final String encode(final byte[] src, final int off,
136: final int len, final boolean breakLines)
137: {
138: final int len43 = len * 4 / 3;
139: final byte[] outBuff = new byte[len43
140: + ((len % 3) > 0 ? 4 : 0)
141: + (breakLines ? (len43 / MAX_LINE_LENGTH)
142: : 0)];
143: int d = 0;
144: int e = 0;
145: final int len2 = len - 2;
146: int lineLength = 0;
147: for (; d < len2; d += 3, e += 4)
148: {
149: encode3to4(src, d + off, 3, outBuff, e);
150: lineLength += 4;
151: if (breakLines && lineLength == MAX_LINE_LENGTH)
152: {
153: outBuff[e + 4] = NEW_LINE;
154: e++;
155: lineLength = 0;
156: }
157: }
158: if (d < len)
159: {
160: encode3to4(src, d + off, len - d, outBuff, e);
161: e += 4;
162: }
163: return new String(outBuff, 0, e);
164: }
165:
166:
172: public static final byte[] decode(final String s)
173: throws UnsupportedEncodingException
174: {
175: final byte[] bytes;
176: bytes = s.getBytes("US-ASCII");
177: return decode(bytes, 0, bytes.length);
178: }
179:
180:
191: public static byte[] decode(final byte[] src, final int off, final int len)
192: {
193: final int len34 = len * 3 / 4;
194: final byte[] outBuff = new byte[len34];
195: int outBuffPosn = 0;
196: final byte[] b4 = new byte[4];
197: int b4Posn = 0;
198: int i;
199: byte sbiCrop, sbiDecode;
200: for (i = off; i < off + len; i++)
201: {
202: sbiCrop = (byte) (src[i] & 0x7F);
203: sbiDecode = DECODABET[sbiCrop];
204: if (sbiDecode >= WHITE_SPACE_ENC)
205: {
206: if (sbiDecode >= EQUALS_SIGN_ENC)
207: {
208: b4[b4Posn++] = sbiCrop;
209: if (b4Posn > 3)
210: {
211: outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);
212: b4Posn = 0;
213:
214: if (sbiCrop == EQUALS_SIGN)
215: break;
216: }
217: }
218: }
219: throw new IllegalArgumentException("Illegal BASE-64 character at #"
220: + i + ": " + src[i] + "(decimal)");
221: }
222: final byte[] result = new byte[outBuffPosn];
223: System.arraycopy(outBuff, 0, result, 0, outBuffPosn);
224: return result;
225: }
226:
227:
246: private static final byte[] encode3to4(final byte[] src, final int sOffset,
247: final int numBytes, final byte[] dest,
248: final int dOffset)
249: {
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261: final int inBuff = (numBytes > 0 ? ((src[sOffset] << 24) >>> 8) : 0)
262: | (numBytes > 1 ? ((src[sOffset + 1] << 24) >>> 16) : 0)
263: | (numBytes > 2 ? ((src[sOffset + 2] << 24) >>> 24) : 0);
264: switch (numBytes)
265: {
266: case 3:
267: dest[dOffset ] = ALPHABET[(inBuff >>> 18)];
268: dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
269: dest[dOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3F];
270: dest[dOffset + 3] = ALPHABET[(inBuff) & 0x3F];
271: break;
272: case 2:
273: dest[dOffset ] = ALPHABET[(inBuff >>> 18)];
274: dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
275: dest[dOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3F];
276: dest[dOffset + 3] = EQUALS_SIGN;
277: break;
278: case 1:
279: dest[dOffset ] = ALPHABET[(inBuff >>> 18)];
280: dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
281: dest[dOffset + 2] = EQUALS_SIGN;
282: dest[dOffset + 3] = EQUALS_SIGN;
283: break;
284: }
285: return dest;
286: }
287:
288:
307: private static final int decode4to3(final byte[] src, final int sOffset,
308: final byte[] dest, final int dOffset)
309: {
310: if (src[sOffset + 2] == EQUALS_SIGN)
311: {
312: final int outBuff = ((DECODABET[src[sOffset ]] & 0xFF) << 18)
313: | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12);
314: dest[dOffset] = (byte)(outBuff >>> 16);
315: return 1;
316: }
317: if (src[sOffset + 3] == EQUALS_SIGN)
318: {
319: final int outBuff = ((DECODABET[src[sOffset ]] & 0xFF) << 18)
320: | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12)
321: | ((DECODABET[src[sOffset + 2]] & 0xFF) << 6);
322: dest[dOffset ] = (byte)(outBuff >>> 16);
323: dest[dOffset + 1] = (byte)(outBuff >>> 8);
324: return 2;
325: }
326: try
327: {
328: final int outBuff = ((DECODABET[src[sOffset ]] & 0xFF) << 18)
329: | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12)
330: | ((DECODABET[src[sOffset + 2]] & 0xFF) << 6)
331: | ((DECODABET[src[sOffset + 3]] & 0xFF));
332: dest[dOffset ] = (byte)(outBuff >> 16);
333: dest[dOffset + 1] = (byte)(outBuff >> 8);
334: dest[dOffset + 2] = (byte) outBuff;
335: return 3;
336: }
337: catch (Exception x)
338: {
339: if (Configuration.DEBUG)
340: {
341: log.fine("" + src[sOffset ] + ": " + (DECODABET[src[sOffset ]]));
342: log.fine("" + src[sOffset + 1] + ": " + (DECODABET[src[sOffset + 1]]));
343: log.fine("" + src[sOffset + 2] + ": " + (DECODABET[src[sOffset + 2]]));
344: log.fine("" + src[sOffset + 3] + ": " + (DECODABET[src[sOffset + 3]]));
345: }
346: return -1;
347: }
348: }
349: }