| 1 package org.alfresco.util; 2 3 50 public class Base64 51 { 52 53 54 55 56 57 public final static int NO_OPTIONS = 0; 58 59 60 public final static int ENCODE = 1; 61 62 63 64 public final static int DECODE = 0; 65 66 67 68 public final static int GZIP = 2; 69 70 71 72 public final static int DONT_BREAK_LINES = 8; 73 74 75 76 77 78 79 private final static int MAX_LINE_LENGTH = 76; 80 81 82 83 private final static byte EQUALS_SIGN = (byte)'='; 84 85 86 87 private final static byte NEW_LINE = (byte)'\n'; 88 89 90 91 private final static String PREFERRED_ENCODING = "UTF-8"; 92 93 94 95 private final static byte[] ALPHABET; 96 private final static byte[] _NATIVE_ALPHABET = 97 { 98 (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', 99 (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', 100 (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', 101 (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', 102 (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', 103 (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', 104 (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', 105 (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', 106 (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', 107 (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/' 108 }; 109 110 111 static 112 { 113 byte[] __bytes; 114 try 115 { 116 __bytes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes( PREFERRED_ENCODING ); 117 } catch (java.io.UnsupportedEncodingException use) 119 { 120 __bytes = _NATIVE_ALPHABET; } ALPHABET = __bytes; 123 } 125 126 130 private final static byte[] DECODABET = 131 { 132 -9,-9,-9,-9,-9,-9,-9,-9,-9, -5,-5, -9,-9, -5, -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, -9,-9,-9,-9,-9, -5, -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, 62, -9,-9,-9, 63, 52,53,54,55,56,57,58,59,60,61, -9,-9,-9, -1, -9,-9,-9, 0,1,2,3,4,5,6,7,8,9,10,11,12,13, 14,15,16,17,18,19,20,21,22,23,24,25, -9,-9,-9,-9,-9,-9, 26,27,28,29,30,31,32,33,34,35,36,37,38, 39,40,41,42,43,44,45,46,47,48,49,50,51, -9,-9,-9,-9 163 }; 164 165 private final static byte WHITE_SPACE_ENC = -5; private final static byte EQUALS_SIGN_ENC = -1; 170 171 172 private Base64(){} 173 174 175 176 177 178 179 194 private static byte[] encode3to4( byte[] b4, byte[] threeBytes, int numSigBytes ) 195 { 196 encode3to4( threeBytes, 0, numSigBytes, b4, 0 ); 197 return b4; 198 } 200 201 222 private static byte[] encode3to4( 223 byte[] source, int srcOffset, int numSigBytes, 224 byte[] destination, int destOffset ) 225 { 226 233 int inBuff = ( numSigBytes > 0 ? ((source[ srcOffset ] << 24) >>> 8) : 0 ) 238 | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24) >>> 16) : 0 ) 239 | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24) >>> 24) : 0 ); 240 241 switch( numSigBytes ) 242 { 243 case 3: 244 destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; 245 destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; 246 destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; 247 destination[ destOffset + 3 ] = ALPHABET[ (inBuff ) & 0x3f ]; 248 return destination; 249 250 case 2: 251 destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; 252 destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; 253 destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; 254 destination[ destOffset + 3 ] = EQUALS_SIGN; 255 return destination; 256 257 case 1: 258 destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; 259 destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; 260 destination[ destOffset + 2 ] = EQUALS_SIGN; 261 destination[ destOffset + 3 ] = EQUALS_SIGN; 262 return destination; 263 264 default: 265 return destination; 266 } } 269 270 271 282 public static String encodeObject( java.io.Serializable serializableObject ) 283 { 284 return encodeObject( serializableObject, NO_OPTIONS ); 285 } 287 288 289 312 public static String encodeObject( java.io.Serializable serializableObject, int options ) 313 { 314 java.io.ByteArrayOutputStream baos = null; 316 java.io.OutputStream b64os = null; 317 java.io.ObjectOutputStream oos = null; 318 java.util.zip.GZIPOutputStream gzos = null; 319 320 int gzip = (options & GZIP); 322 int dontBreakLines = (options & DONT_BREAK_LINES); 323 324 try 325 { 326 baos = new java.io.ByteArrayOutputStream (); 328 b64os = new Base64.OutputStream( baos, ENCODE | dontBreakLines ); 329 330 if( gzip == GZIP ) 332 { 333 gzos = new java.util.zip.GZIPOutputStream ( b64os ); 334 oos = new java.io.ObjectOutputStream ( gzos ); 335 } else 337 oos = new java.io.ObjectOutputStream ( b64os ); 338 339 oos.writeObject( serializableObject ); 340 } catch( java.io.IOException e ) 342 { 343 e.printStackTrace(); 344 return null; 345 } finally 347 { 348 try{ oos.close(); } catch( Exception e ){} 349 try{ gzos.close(); } catch( Exception e ){} 350 try{ b64os.close(); } catch( Exception e ){} 351 try{ baos.close(); } catch( Exception e ){} 352 } 354 try 356 { 357 return new String ( baos.toByteArray(), PREFERRED_ENCODING ); 358 } catch (java.io.UnsupportedEncodingException uue) 360 { 361 return new String ( baos.toByteArray() ); 362 } 364 } 366 367 368 375 public static String encodeBytes( byte[] source ) 376 { 377 return encodeBytes( source, 0, source.length, NO_OPTIONS ); 378 } 380 381 382 402 public static String encodeBytes( byte[] source, int options ) 403 { 404 return encodeBytes( source, 0, source.length, options ); 405 } 407 408 417 public static String encodeBytes( byte[] source, int off, int len ) 418 { 419 return encodeBytes( source, off, len, NO_OPTIONS ); 420 } 422 423 424 446 public static String encodeBytes( byte[] source, int off, int len, int options ) 447 { 448 int dontBreakLines = ( options & DONT_BREAK_LINES ); 450 int gzip = ( options & GZIP ); 451 452 if( gzip == GZIP ) 454 { 455 java.io.ByteArrayOutputStream baos = null; 456 java.util.zip.GZIPOutputStream gzos = null; 457 Base64.OutputStream b64os = null; 458 459 460 try 461 { 462 baos = new java.io.ByteArrayOutputStream (); 464 b64os = new Base64.OutputStream( baos, ENCODE | dontBreakLines ); 465 gzos = new java.util.zip.GZIPOutputStream ( b64os ); 466 467 gzos.write( source, off, len ); 468 gzos.close(); 469 } catch( java.io.IOException e ) 471 { 472 e.printStackTrace(); 473 return null; 474 } finally 476 { 477 try{ gzos.close(); } catch( Exception e ){} 478 try{ b64os.close(); } catch( Exception e ){} 479 try{ baos.close(); } catch( Exception e ){} 480 } 482 try 484 { 485 return new String ( baos.toByteArray(), PREFERRED_ENCODING ); 486 } catch (java.io.UnsupportedEncodingException uue) 488 { 489 return new String ( baos.toByteArray() ); 490 } } 493 else 495 { 496 boolean breakLines = dontBreakLines == 0; 498 499 int len43 = len * 4 / 3; 500 byte[] outBuff = new byte[ ( len43 ) + ( (len % 3) > 0 ? 4 : 0 ) + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; int d = 0; 504 int e = 0; 505 int len2 = len - 2; 506 int lineLength = 0; 507 for( ; d < len2; d+=3, e+=4 ) 508 { 509 encode3to4( source, d+off, 3, outBuff, e ); 510 511 lineLength += 4; 512 if( breakLines && lineLength == MAX_LINE_LENGTH ) 513 { 514 outBuff[e+4] = NEW_LINE; 515 e++; 516 lineLength = 0; 517 } } 520 if( d < len ) 521 { 522 encode3to4( source, d+off, len - d, outBuff, e ); 523 e += 4; 524 } 526 527 try 529 { 530 return new String ( outBuff, 0, e, PREFERRED_ENCODING ); 531 } catch (java.io.UnsupportedEncodingException uue) 533 { 534 return new String ( outBuff, 0, e ); 535 } 537 } 539 } 541 542 543 544 545 546 547 548 570 private static int decode4to3( byte[] source, int srcOffset, byte[] destination, int destOffset ) 571 { 572 if( source[ srcOffset + 2] == EQUALS_SIGN ) 574 { 575 int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) 579 | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF ) << 12 ); 580 581 destination[ destOffset ] = (byte)( outBuff >>> 16 ); 582 return 1; 583 } 584 585 else if( source[ srcOffset + 3 ] == EQUALS_SIGN ) 587 { 588 int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) 593 | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) 594 | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6 ); 595 596 destination[ destOffset ] = (byte)( outBuff >>> 16 ); 597 destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 ); 598 return 2; 599 } 600 601 else 603 { 604 try{ 605 int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) 611 | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) 612 | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6) 613 | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF ) ); 614 615 616 destination[ destOffset ] = (byte)( outBuff >> 16 ); 617 destination[ destOffset + 1 ] = (byte)( outBuff >> 8 ); 618 destination[ destOffset + 2 ] = (byte)( outBuff ); 619 620 return 3; 621 }catch( Exception e){ 622 System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset ] ] ) ); 623 System.out.println(""+source[srcOffset+1]+ ": " + ( DECODABET[ source[ srcOffset + 1 ] ] ) ); 624 System.out.println(""+source[srcOffset+2]+ ": " + ( DECODABET[ source[ srcOffset + 2 ] ] ) ); 625 System.out.println(""+source[srcOffset+3]+ ": " + ( DECODABET[ source[ srcOffset + 3 ] ] ) ); 626 return -1; 627 } } 629 } 631 632 633 634 645 public static byte[] decode( byte[] source, int off, int len ) 646 { 647 int len34 = len * 3 / 4; 648 byte[] outBuff = new byte[ len34 ]; int outBuffPosn = 0; 650 651 byte[] b4 = new byte[4]; 652 int b4Posn = 0; 653 int i = 0; 654 byte sbiCrop = 0; 655 byte sbiDecode = 0; 656 for( i = off; i < off+len; i++ ) 657 { 658 sbiCrop = (byte)(source[i] & 0x7f); sbiDecode = DECODABET[ sbiCrop ]; 660 661 if( sbiDecode >= WHITE_SPACE_ENC ) { 663 if( sbiDecode >= EQUALS_SIGN_ENC ) 664 { 665 b4[ b4Posn++ ] = sbiCrop; 666 if( b4Posn > 3 ) 667 { 668 outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn ); 669 b4Posn = 0; 670 671 if( sbiCrop == EQUALS_SIGN ) 673 break; 674 } 676 } 678 } else 680 { 681 System.err.println( "Bad Base64 input character at " + i + ": " + source[i] + "(decimal)" ); 682 return null; 683 } } 686 byte[] out = new byte[ outBuffPosn ]; 687 System.arraycopy( outBuff, 0, out, 0, outBuffPosn ); 688 return out; 689 } 691 692 693 694 702 public static byte[] decode( String s ) 703 { 704 byte[] bytes; 705 try 706 { 707 bytes = s.getBytes( PREFERRED_ENCODING ); 708 } catch( java.io.UnsupportedEncodingException uee ) 710 { 711 bytes = s.getBytes(); 712 } 715 bytes = decode( bytes, 0, bytes.length ); 717 718 719 if( bytes != null && bytes.length >= 4 ) 722 { 723 724 int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); 725 if( java.util.zip.GZIPInputStream.GZIP_MAGIC == head ) 726 { 727 java.io.ByteArrayInputStream bais = null; 728 java.util.zip.GZIPInputStream gzis = null; 729 java.io.ByteArrayOutputStream baos = null; 730 byte[] buffer = new byte[2048]; 731 int length = 0; 732 733 try 734 { 735 baos = new java.io.ByteArrayOutputStream (); 736 bais = new java.io.ByteArrayInputStream ( bytes ); 737 gzis = new java.util.zip.GZIPInputStream ( bais ); 738 739 while( ( length = gzis.read( buffer ) ) >= 0 ) 740 { 741 baos.write(buffer,0,length); 742 } 744 bytes = baos.toByteArray(); 746 747 } catch( java.io.IOException e ) 749 { 750 } finally 753 { 754 try{ baos.close(); } catch( Exception e ){} 755 try{ gzis.close(); } catch( Exception e ){} 756 try{ bais.close(); } catch( Exception e ){} 757 } 759 } } 762 return bytes; 763 } 765 766 767 768 776 public static Object decodeToObject( String encodedObject ) 777 { 778 byte[] objBytes = decode( encodedObject ); 780 781 &n
|