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