1 package com.atlassian.user.util;
2
3
4
5
6
7 public final class Base64Encoder
8 {
9
10
11
12 private final static char[] enc_table = {
13 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
14 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
15 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
16 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
17 '4', '5', '6', '7', '8', '9', '+', '/'
18 };
19
20
21 private final static byte[] dec_table = {
22 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
23 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
24 -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57,
25 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
26 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1,
27 -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
28 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1,
29 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
30 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
31 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
32 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
33 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
34 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
35 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36 -1,
37 };
38
39
40
41 public static byte[] decode(byte[] data) {
42 int padCount = 0;
43 int i;
44 int len = data.length;
45 int real_len = 0;
46
47 for (i = len - 1; i >= 0; --i) {
48 if (data[i] > ' ') {
49 real_len++;
50 }
51
52 if (data[i] == 0x3D) {
53 padCount++;
54 }
55 }
56
57 if ((real_len % 4) != 0) {
58 throw new IllegalArgumentException("Length not a multiple of 4");
59 }
60
61 int ret_len = ((real_len / 4) * 3) - padCount;
62 byte[] ret = new byte[ret_len];
63
64 i = 0;
65
66 byte[] t = new byte[4];
67 int output_index = 0;
68 int j = 0;
69 t[0] = t[1] = t[2] = t[3] = 0x3D;
70
71 while (i < len) {
72 byte c = data[i++];
73
74 if (c > ' ') {
75 t[j++] = c;
76 }
77
78 if (j == 4) {
79 output_index += decode(ret, output_index, t[0], t[1], t[2], t[3]);
80 j = 0;
81 t[0] = t[1] = t[2] = t[3] = 0x3D;
82 }
83 }
84
85 if (j > 0) {
86 decode(ret, output_index, t[0], t[1], t[2], t[3]);
87 }
88
89 return ret;
90 }
91
92 public static int decode(byte[] ret, int ret_off, byte a, byte b, byte c, byte d) {
93 byte da = dec_table[a];
94 byte db = dec_table[b];
95 byte dc = dec_table[c];
96 byte dd = dec_table[d];
97
98 if ((da == -1) || (db == -1) || ((dc == -1) && (c != 0x3D)) || ((dd == -1) && (d != 0x3D))) {
99 throw new IllegalArgumentException("Invalid character [" + (a & 0xFF) + ", " + (b & 0xFF) + ", " + (c & 0xFF) + ", " + (d & 0xFF) + "]");
100 }
101
102 ret[ret_off++] = (byte) ((da << 2) | db >>> 4);
103
104 if (c == 0x3D) {
105 return 1;
106 }
107
108 ret[ret_off++] = (byte) ((db << 4) | dc >>> 2);
109
110 if (d == 0x3D) {
111 return 2;
112 }
113
114 ret[ret_off++] = (byte) ((dc << 6) | dd);
115
116 return 3;
117 }
118
119 public static byte[] encode(byte[] data) {
120 int i = 0;
121 int j = 0;
122 int len = data.length;
123 int delta = len % 3;
124 int outlen = (((len + 2) / 3) * 4) + ((len == 0) ? 2 : 0);
125 byte[] output = new byte[outlen];
126
127 byte a;
128 byte b;
129 byte c;
130
131 for (int count = len / 3; count > 0; count--) {
132 a = data[i++];
133 b = data[i++];
134 c = data[i++];
135 output[j++] = (byte) (enc_table[(a >>> 2) & 0x3F]);
136 output[j++] = (byte) (enc_table[((a << 4) & 0x30) + ((b >>> 4) & 0x0F)]);
137 output[j++] = (byte) (enc_table[((b << 2) & 0x3C) + ((c >>> 6) & 0x03)]);
138 output[j++] = (byte) (enc_table[c & 0x3F]);
139 }
140
141 if (delta == 1) {
142 a = data[i++];
143 output[j++] = (byte) (enc_table[(a >>> 2) & 0x3F]);
144 output[j++] = (byte) (enc_table[((a << 4) & 0x30)]);
145 output[j++] = (byte) '=';
146 output[j++] = (byte) '=';
147 } else if (delta == 2) {
148 a = data[i++];
149 b = data[i++];
150 output[j++] = (byte) (enc_table[(a >>> 2) & 0x3F]);
151 output[j++] = (byte) (enc_table[((a << 4) & 0x30) + ((b >>> 4) & 0x0F)]);
152 output[j++] = (byte) (enc_table[((b << 2) & 0x3C)]);
153 output[j++] = (byte) '=';
154 }
155
156 if (j != outlen) {
157 throw new IllegalArgumentException("output length was not the expected");
158 }
159
160 return output;
161 }
162 }