1 21 22 27 28 package com.sun.mail.util; 29 30 import java.io.*; 31 32 41 42 public class BASE64DecoderStream extends FilterInputStream { 43 private byte[] buffer = new byte[3]; 45 private int bufsize = 0; private int index = 0; 48 private byte[] input_buffer = new byte[78*105]; 51 private int input_pos = 0; 52 private int input_len = 0;; 53 54 private boolean ignoreErrors = false; 55 56 64 public BASE64DecoderStream(InputStream in) { 65 super(in); 66 try { 67 String s = System.getProperty("mail.mime.base64.ignoreerrors"); 68 ignoreErrors = s != null && !s.equalsIgnoreCase("false"); 70 } catch (SecurityException sex) { 71 } 73 } 74 75 81 public BASE64DecoderStream(InputStream in, boolean ignoreErrors) { 82 super(in); 83 this.ignoreErrors = ignoreErrors; 84 } 85 86 99 public int read() throws IOException { 100 if (index >= bufsize) { 101 bufsize = decode(buffer, 0, buffer.length); 102 if (bufsize <= 0) return -1; 104 index = 0; } 106 return buffer[index++] & 0xff; } 108 109 123 public int read(byte[] buf, int off, int len) throws IOException { 124 int off0 = off; 126 while (index < bufsize && len > 0) { 127 buf[off++] = buffer[index++]; 128 len--; 129 } 130 if (index >= bufsize) 131 bufsize = index = 0; 132 133 int bsize = (len / 3) * 3; if (bsize > 0) { 135 int size = decode(buf, off, bsize); 136 off += size; 137 len -= size; 138 139 if (size != bsize) { if (off == off0) return -1; 142 else return off - off0; 144 } 145 } 146 147 for (; len > 0; len--) { 149 int c = read(); 150 if (c == -1) break; 152 buf[off++] = (byte)c; 153 } 154 155 if (off == off0) return -1; 157 else return off - off0; 159 } 160 161 165 public boolean markSupported() { 166 return false; } 168 169 175 public int available() throws IOException { 176 return ((in.available() * 3)/4 + (bufsize-index)); 179 } 180 181 185 private final static char pem_array[] = { 186 'A','B','C','D','E','F','G','H', 'I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X', 'Y','Z','a','b','c','d','e','f', 'g','h','i','j','k','l','m','n', 'o','p','q','r','s','t','u','v', 'w','x','y','z','0','1','2','3', '4','5','6','7','8','9','+','/' }; 195 196 private final static byte pem_convert_array[] = new byte[256]; 197 198 static { 199 for (int i = 0; i < 255; i++) 200 pem_convert_array[i] = -1; 201 for (int i = 0; i < pem_array.length; i++) 202 pem_convert_array[pem_array[i]] = (byte)i; 203 } 204 205 219 private int decode(byte[] outbuf, int pos, int len) throws IOException { 220 int pos0 = pos; 221 while (len >= 3) { 222 227 int got = 0; 228 int val = 0; 229 while (got < 4) { 230 int i = getByte(); 231 if (i == -1 || i == -2) { 232 boolean atEOF; 233 if (i == -1) { 234 if (got == 0) 235 return pos - pos0; 236 if (!ignoreErrors) 237 throw new IOException("Error in encoded stream: " + 238 "needed 4 valid base64 characters " + 239 "but only got " + got + " before EOF" + 240 recentChars()); 241 atEOF = true; } else { if (got < 2 && !ignoreErrors) 246 throw new IOException("Error in encoded stream: " + 247 "needed at least 2 valid base64 characters," + 248 " but only got " + got + 249 " before padding character (=)" + 250 recentChars()); 251 252 if (got == 0) 254 return pos - pos0; 255 atEOF = false; } 257 258 260 int size = got - 1; 263 if (size == 0) 264 size = 1; 265 266 got++; 268 val <<= 6; 269 270 while (got < 4) { 271 if (!atEOF) { 272 i = getByte(); 275 if (i == -1) { 276 if (!ignoreErrors) 277 throw new IOException( 278 "Error in encoded stream: " + 279 "hit EOF while looking for " + 280 "padding characters (=)" + 281 recentChars()); 282 } else if (i != -2) { 283 if (!ignoreErrors) 284 throw new IOException( 285 "Error in encoded stream: " + 286 "found valid base64 character after " + 287 "a padding character (=)" + 288 recentChars()); 289 } 290 } 291 val <<= 6; 292 got++; 293 } 294 295 val >>= 8; if (size == 2) 298 outbuf[pos + 1] = (byte)(val & 0xff); 299 val >>= 8; 300 outbuf[pos] = (byte)(val & 0xff); 301 len -= size; 302 pos += size; 303 return pos - pos0; 304 } else { 305 val <<= 6; 307 got++; 308 val |= i; 309 } 310 } 311 312 outbuf[pos + 2] = (byte)(val & 0xff); 314 val >>= 8; 315 outbuf[pos + 1] = (byte)(val & 0xff); 316 val >>= 8; 317 outbuf[pos] = (byte)(val & 0xff); 318 len -= 3; 319 pos += 3; 320 } 321 return pos - pos0; 322 } 323 324 332 private int getByte() throws IOException { 333 int c; 334 do { 335 if (input_pos >= input_len) { 336 try { 337 input_len = in.read(input_buffer); 338 } catch (EOFException ex) { 339 return -1; 340 } 341 if (input_len <= 0) 342 return -1; 343 input_pos = 0; 344 } 345 c = input_buffer[input_pos++] & 0xff; 347 if (c == '=') 349 return -2; 350 c = pem_convert_array[c]; 352 } while (c == -1); 354 return c; 355 } 356 357 360 private String recentChars() { 361 String errstr = ""; 364 int nc = input_pos > 10 ? 10 : input_pos; 365 if (nc > 0) { 366 errstr += ", the " + nc + 367 " most recent characters were: \""; 368 for (int k = input_pos - nc; k < input_pos; k++) { 369 char c = (char)(input_buffer[k] & 0xff); 370 switch (c) { 371 case '\r': errstr += "\\r"; break; 372 case '\n': errstr += "\\n"; break; 373 case '\t': errstr += "\\t"; break; 374 default: 375 if (c >= ' ' && c < 0177) 376 errstr += c; 377 else 378 errstr += ("\\" + (int)c); 379 } 380 } 381 errstr += "\""; 382 } 383 return errstr; 384 } 385 386 395 public static byte[] decode(byte[] inbuf) { 396 int size = (inbuf.length / 4) * 3; 397 if (size == 0) 398 return inbuf; 399 400 if (inbuf[inbuf.length - 1] == '=') { 401 size--; 402 if (inbuf[inbuf.length - 2] == '=') 403 size--; 404 } 405 byte[] outbuf = new byte[size]; 406 407 int inpos = 0, outpos = 0; 408 size = inbuf.length; 409 while (size > 0) { 410 int val; 411 int osize = 3; 412 val = pem_convert_array[inbuf[inpos++] & 0xff]; 413 val <<= 6; 414 val |= pem_convert_array[inbuf[inpos++] & 0xff]; 415 val <<= 6; 416 if (inbuf[inpos] != '=') val |= pem_convert_array[inbuf[inpos++] & 0xff]; 418 else 419 osize--; 420 val <<= 6; 421 if (inbuf[inpos] != '=') val |= pem_convert_array[inbuf[inpos++] & 0xff]; 423 else 424 osize--; 425 if (osize > 2) 426 outbuf[outpos + 2] = (byte)(val & 0xff); 427 val >>= 8; 428 if (osize > 1) 429 outbuf[outpos + 1] = (byte)(val & 0xff); 430 val >>= 8; 431 outbuf[outpos] = (byte)(val & 0xff); 432 outpos += osize; 433 size -= 4; 434 } 435 return outbuf; 436 } 437 438 449 } 450 | Popular Tags |