001
014
015 package com.liferay.portal.kernel.io;
016
017 import com.liferay.portal.kernel.util.CharPool;
018
019 import java.io.IOException;
020 import java.io.InputStream;
021
022
025 public class Base64InputStream extends InputStream {
026
027 public Base64InputStream(InputStream inputStream) {
028 _inputStream = inputStream;
029 _unitBufferIndex = 0;
030 _avaiableBytes = 0;
031 _unitBuffer = new byte[3];
032 }
033
034 public int available() throws IOException {
035 return ((_inputStream.available() * 3) / 4) + _avaiableBytes;
036 }
037
038 public int read() throws IOException {
039 if (_avaiableBytes == 0) {
040 _avaiableBytes = decodeUnit(_unitBuffer, 0);
041
042 if (_avaiableBytes <= 0) {
043 return -1;
044 }
045
046 _unitBufferIndex = 0;
047 }
048
049 _avaiableBytes--;
050
051 return _unitBuffer[_unitBufferIndex++] & 0xff;
052 }
053
054 public int read(byte[] buffer, int offset, int length) throws IOException {
055 if ((length <= 0) || (offset < 0)) {
056 return -1;
057 }
058
059 int initialLength = length;
060
061 while ((_avaiableBytes > 0) && (length > 0)) {
062 buffer[offset++] = _unitBuffer[_unitBufferIndex++];
063
064 _avaiableBytes--;
065 length--;
066 }
067
068 int bytesLength = length - (length % 3);
069
070 while (bytesLength > 0) {
071 int returnValue = decodeUnit(buffer, offset);
072
073 if (returnValue > 0) {
074 offset += returnValue;
075 length -= returnValue;
076 }
077
078 if (returnValue < 3) {
079 if (initialLength == length) {
080 return -1;
081 }
082
083 return initialLength - length;
084 }
085
086 bytesLength -= 3;
087 }
088
089 while (length > 0) {
090 int intValue = read();
091
092 if (intValue == -1) {
093 break;
094 }
095
096 buffer[offset++] = (byte)intValue;
097
098 length--;
099 }
100
101 if (initialLength == length) {
102 return -1;
103 }
104
105 return initialLength - length;
106 }
107
108 public long skip(long skip) throws IOException {
109 long initialSkip = skip;
110
111 while (skip > 0) {
112 if (read() <= 0) {
113 break;
114 }
115
116 skip--;
117 }
118
119 return initialSkip - skip;
120 }
121
122 protected int decode(
123 byte[] bytes, byte[] outputBuffer, int position, int padNumber) {
124
125 int intValue = 0;
126
127 for(int next = 0; next < 4; next++) {
128 intValue <<= 6;
129 intValue |= bytes[next];
130 }
131
132 if (padNumber == 2) {
133 intValue >>= 16;
134
135 outputBuffer[position] = (byte)(intValue & 0xff);
136
137 return 1;
138 }
139 else if (padNumber == 1) {
140 intValue >>= 8;
141
142 outputBuffer[position + 1] = (byte)(intValue & 0xff);
143
144 intValue >>= 8;
145
146 outputBuffer[position] = (byte)(intValue & 0xff);
147
148 return 2;
149 }
150 else if (padNumber == 0) {
151 outputBuffer[position + 2] = (byte)(intValue & 0xff);
152
153 intValue >>= 8;
154
155 outputBuffer[position + 1] = (byte)(intValue & 0xff);
156
157 intValue >>= 8;
158
159 outputBuffer[position] = (byte)(intValue & 0xff);
160
161 return 3;
162 }
163 else {
164 return -1;
165 }
166 }
167
168 protected int decodeUnit(byte[] outputBuffer, int position)
169 throws IOException {
170
171 int intValue = -1;
172 int padNumber = 0;
173 int count = 0;
174 byte[] decodeUnitBuffer = new byte[4];
175
176 while (count < 4) {
177 intValue = getEncodedByte();
178
179 if (intValue == -1) {
180 return -1;
181 }
182
183 if (intValue == -2) {
184 if (count < 2) {
185 return -1;
186 }
187
188 padNumber++;
189 count++;
190
191 while (count < 4) {
192 intValue = getEncodedByte();
193
194 if (intValue != -2) {
195 return -1;
196 }
197
198 padNumber++;
199 count++;
200 }
201
202 int returnValue = decode(
203 decodeUnitBuffer, outputBuffer, position, padNumber);
204
205 return returnValue;
206 }
207
208 decodeUnitBuffer[count++] = (byte)intValue;
209 }
210
211 return decode(decodeUnitBuffer, outputBuffer, position, padNumber);
212 }
213
214 protected int getByte(char character) {
215 if ((character >= CharPool.UPPER_CASE_A) &&
216 (character <= CharPool.UPPER_CASE_Z)) {
217
218 return character - 65;
219 }
220
221 if ((character >= CharPool.LOWER_CASE_A) &&
222 (character <= CharPool.LOWER_CASE_Z)) {
223
224 return (character - 97) + 26;
225 }
226
227 if ((character >= CharPool.NUMBER_0) &&
228 (character <= CharPool.NUMBER_9)) {
229
230 return (character - 48) + 52;
231 }
232
233 if (character == CharPool.PLUS) {
234 return 62;
235 }
236
237 if (character == CharPool.SLASH) {
238 return 63;
239 }
240
241 if (character != CharPool.EQUAL) {
242 return -1;
243 }
244 else {
245 return 0;
246 }
247 }
248
249 protected int getEncodedByte() throws IOException {
250 while (true) {
251 int returnValue = _inputStream.read();
252
253 if (returnValue == -1) {
254 return -1;
255 }
256
257 char character = (char)(returnValue & 0xff);
258
259 if (character == CharPool.EQUAL) {
260 return -2;
261 }
262
263 int byteValue = getByte(character);
264
265 if (byteValue == -1) {
266 continue;
267 }
268
269 return byteValue;
270 }
271 }
272
273 private int _avaiableBytes;
274 private InputStream _inputStream;
275 private byte[] _unitBuffer;
276 private int _unitBufferIndex;
277
278 }