1
14
15 package com.liferay.portal.kernel.io;
16
17 import com.liferay.portal.kernel.util.CharPool;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21
22
27 public class Base64InputStream extends InputStream {
28
29 public Base64InputStream(InputStream inputStream) {
30 _inputStream = inputStream;
31 _unitBufferIndex = 0;
32 _avaiableBytes = 0;
33 _unitBuffer = new byte[3];
34 }
35
36 public int available() throws IOException {
37 return ((_inputStream.available() * 3) / 4) + _avaiableBytes;
38 }
39
40 public int read() throws IOException {
41 if (_avaiableBytes == 0) {
42 _avaiableBytes = decodeUnit(_unitBuffer, 0);
43
44 if (_avaiableBytes <= 0) {
45 return -1;
46 }
47
48 _unitBufferIndex = 0;
49 }
50
51 _avaiableBytes--;
52
53 return _unitBuffer[_unitBufferIndex++] & 0xff;
54 }
55
56 public int read(byte[] buffer, int offset, int length) throws IOException {
57 if ((length <= 0) || (offset < 0)) {
58 return -1;
59 }
60
61 int initialLength = length;
62
63 while ((_avaiableBytes > 0) && (length > 0)) {
64 buffer[offset++] = _unitBuffer[_unitBufferIndex++];
65
66 _avaiableBytes--;
67 length--;
68 }
69
70 int bytesLength = length - (length % 3);
71
72 while (bytesLength > 0) {
73 int returnValue = decodeUnit(buffer, offset);
74
75 if (returnValue > 0) {
76 offset += returnValue;
77 length -= returnValue;
78 }
79
80 if (returnValue < 3) {
81 if (initialLength == length) {
82 return -1;
83 }
84
85 return initialLength - length;
86 }
87
88 bytesLength -= 3;
89 }
90
91 while (length > 0) {
92 int intValue = read();
93
94 if (intValue == -1) {
95 break;
96 }
97
98 buffer[offset++] = (byte)intValue;
99
100 length--;
101 }
102
103 if (initialLength == length) {
104 return -1;
105 }
106
107 return initialLength - length;
108 }
109
110 public long skip(long skip) throws IOException {
111 long initialSkip = skip;
112
113 while (skip > 0) {
114 if (read() <= 0) {
115 break;
116 }
117
118 skip--;
119 }
120
121 return initialSkip - skip;
122 }
123
124 protected int decode(
125 byte[] bytes, byte[] outputBuffer, int position, int padNumber) {
126
127 int intValue = 0;
128
129 for(int next = 0; next < 4; next++) {
130 intValue <<= 6;
131 intValue |= bytes[next];
132 }
133
134 if (padNumber == 2) {
135 intValue >>= 16;
136
137 outputBuffer[position] = (byte)(intValue & 0xff);
138
139 return 1;
140 }
141 else if (padNumber == 1) {
142 intValue >>= 8;
143
144 outputBuffer[position + 1] = (byte)(intValue & 0xff);
145
146 intValue >>= 8;
147
148 outputBuffer[position] = (byte)(intValue & 0xff);
149
150 return 2;
151 }
152 else if (padNumber == 0) {
153 outputBuffer[position + 2] = (byte)(intValue & 0xff);
154
155 intValue >>= 8;
156
157 outputBuffer[position + 1] = (byte)(intValue & 0xff);
158
159 intValue >>= 8;
160
161 outputBuffer[position] = (byte)(intValue & 0xff);
162
163 return 3;
164 }
165 else {
166 return -1;
167 }
168 }
169
170 protected int decodeUnit(byte[] outputBuffer, int position)
171 throws IOException {
172
173 int intValue = -1;
174 int padNumber = 0;
175 int count = 0;
176 byte[] decodeUnitBuffer = new byte[4];
177
178 while (count < 4) {
179 intValue = getEncodedByte();
180
181 if (intValue == -1) {
182 return -1;
183 }
184
185 if (intValue == -2) {
186 if (count < 2) {
187 return -1;
188 }
189
190 padNumber++;
191 count++;
192
193 while (count < 4) {
194 intValue = getEncodedByte();
195
196 if (intValue != -2) {
197 return -1;
198 }
199
200 padNumber++;
201 count++;
202 }
203
204 int returnValue = decode(
205 decodeUnitBuffer, outputBuffer, position, padNumber);
206
207 return returnValue;
208 }
209
210 decodeUnitBuffer[count++] = (byte)intValue;
211 }
212
213 return decode(decodeUnitBuffer, outputBuffer, position, padNumber);
214 }
215
216 protected int getByte(char character) {
217 if ((character >= CharPool.UPPER_CASE_A) &&
218 (character <= CharPool.UPPER_CASE_Z)) {
219
220 return character - 65;
221 }
222
223 if ((character >= CharPool.LOWER_CASE_A) &&
224 (character <= CharPool.LOWER_CASE_Z)) {
225
226 return (character - 97) + 26;
227 }
228
229 if ((character >= CharPool.NUMBER_0) &&
230 (character <= CharPool.NUMBER_9)) {
231
232 return (character - 48) + 52;
233 }
234
235 if (character == CharPool.PLUS) {
236 return 62;
237 }
238
239 if (character == CharPool.SLASH) {
240 return 63;
241 }
242
243 if (character != CharPool.EQUAL) {
244 return -1;
245 }
246 else {
247 return 0;
248 }
249 }
250
251 protected int getEncodedByte() throws IOException {
252 while (true) {
253 int returnValue = _inputStream.read();
254
255 if (returnValue == -1) {
256 return -1;
257 }
258
259 char character = (char)(returnValue & 0xff);
260
261 if (character == CharPool.EQUAL) {
262 return -2;
263 }
264
265 int byteValue = getByte(character);
266
267 if (byteValue == -1) {
268 continue;
269 }
270
271 return byteValue;
272 }
273 }
274
275 private int _avaiableBytes;
276 private InputStream _inputStream;
277 private byte[] _unitBuffer;
278 private int _unitBufferIndex;
279
280 }