1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.castor.core.util;
17
18 import java.io.ByteArrayOutputStream;
19
20
21
22
23
24
25
26
27
28 public final class Base64Decoder {
29
30 private static final int SEXTET_1_MASK = 0x03FFFF;
31
32
33 private static final int SEXTET_2_MASK = 0xFC0FFF;
34
35
36 private static final int SEXTET_3_MASK = 0xFFF03F;
37
38
39 private static final int SEXTET_4_MASK = 0xFFFFC0;
40
41
42 private static final int SHIFT_1_SEXTET = 6;
43
44
45 private static final int SHIFT_2_SEXTET = 12;
46
47
48 private static final int SHIFT_3_SEXTET = 18;
49
50
51 private static final int SEXTET_2 = 2;
52
53
54 private static final int SEXTET_3 = 3;
55
56
57 private static final int SEXTET_4 = 4;
58
59
60 private static final int OCTET_MASK = 0xFF;
61
62
63 private static final int SHIFT_1_OCTET = 8;
64
65
66 private static final int SHIFT_2_OCTET = 16;
67
68
69 private static final byte SPC = 127;
70
71
72 private static final byte PAD = 64;
73
74
75 private static final byte[] MAP = {
76 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
77 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
78 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
79 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
80 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
81 SPC, SPC, SPC, 62, SPC, SPC, SPC, 63,
82 52, 53, 54, 55, 56, 57, 58, 59,
83 60, 61, SPC, SPC, SPC, PAD, SPC, SPC,
84 SPC, 0, 1, 2, 3, 4, 5, 6,
85 7, 8, 9, 10, 11, 12, 13, 14,
86 15, 16, 17, 18, 19, 20, 21, 22,
87 23, 24, 25, SPC, SPC, SPC, SPC, SPC,
88 SPC, 26, 27, 28, 29, 30, 31, 32,
89 33, 34, 35, 36, 37, 38, 39, 40,
90 41, 42, 43, 44, 45, 46, 47, 48,
91 49, 50, 51, SPC, SPC, SPC, SPC, SPC,
92 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
93 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
94 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
95 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
96 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
97 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
98 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
99 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
100 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
101 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
102 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
103 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
104 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
105 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
106 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
107 SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC,
108 };
109
110
111 private int _buffer = 0;
112
113
114 private int _sextets = 0;
115
116
117 private ByteArrayOutputStream _stream = new ByteArrayOutputStream();
118
119
120
121
122
123
124
125 public static byte[] decode(final String str) {
126 Base64Decoder dec = new Base64Decoder();
127 dec.translate(str);
128 return dec.getByteArray();
129 }
130
131
132
133
134
135 public Base64Decoder() { }
136
137
138
139
140
141
142
143
144
145
146
147
148 public void translate(final String string) {
149 int len = string.length();
150 int index = 0;
151 int data = MAP[string.charAt(index)];
152 while ((index < len) && (data != PAD)) {
153 if (data != SPC) {
154 if (_sextets == 0) {
155 _buffer = (_buffer & SEXTET_1_MASK) | (data << SHIFT_3_SEXTET);
156 } else if (_sextets == 1) {
157 _buffer = (_buffer & SEXTET_2_MASK) | (data << SHIFT_2_SEXTET);
158 } else if (_sextets == 2) {
159 _buffer = (_buffer & SEXTET_3_MASK) | (data << SHIFT_1_SEXTET);
160 } else {
161 _buffer = (_buffer & SEXTET_4_MASK) | data;
162 }
163
164 if ((++_sextets) == SEXTET_4) { decode(); }
165 }
166
167 if (++index < len) { data = MAP[string.charAt(index)]; }
168 }
169
170 if (_sextets > 0) { decodeWithPadding(); }
171 }
172
173
174
175
176 private void decode() {
177 _stream.write((byte) ((_buffer >> SHIFT_2_OCTET) & OCTET_MASK));
178 _stream.write((byte) ((_buffer >> SHIFT_1_OCTET) & OCTET_MASK));
179 _stream.write((byte) (_buffer & OCTET_MASK));
180 _buffer = 0;
181 _sextets = 0;
182 }
183
184
185
186
187 private void decodeWithPadding() {
188 if (_sextets >= SEXTET_2) {
189 _stream.write((byte) ((_buffer >> SHIFT_2_OCTET) & OCTET_MASK));
190 }
191 if (_sextets >= SEXTET_3) {
192 _stream.write((byte) ((_buffer >> SHIFT_1_OCTET) & OCTET_MASK));
193 }
194 if (_sextets >= SEXTET_4) {
195 _stream.write((byte) (_buffer & OCTET_MASK));
196 }
197 _buffer = 0;
198 _sextets = 0;
199 }
200
201
202
203
204
205
206 public byte[] getByteArray() {
207 return _stream.toByteArray();
208 }
209 }