1 46 package org.drftpd.slave.async; 47 48 public class Base64 { 49 50 51 52 53 54 public final static int NO_OPTIONS = 0; 55 56 57 public final static int ENCODE = 1; 58 59 60 61 public final static int DECODE = 0; 62 63 64 65 public final static int GZIP = 2; 66 67 68 69 public final static int DONT_BREAK_LINES = 8; 70 71 72 73 74 75 76 private final static int MAX_LINE_LENGTH = 76; 77 78 79 80 private final static byte EQUALS_SIGN = (byte)'='; 81 82 83 84 private final static byte NEW_LINE = (byte)'\n'; 85 86 87 88 private final static String PREFERRED_ENCODING = "UTF-8"; 89 90 91 92 private final static byte[] ALPHABET; 93 private final static byte[] _NATIVE_ALPHABET = { 94 (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', 95 (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', 96 (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', 97 (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', 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)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', 103 (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/' 104 }; 105 106 107 static { 108 byte[] __bytes; 109 try { 110 __bytes = new String ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/").getBytes( PREFERRED_ENCODING ); 111 } catch (java.io.UnsupportedEncodingException use) { 113 __bytes = _NATIVE_ALPHABET; } ALPHABET = __bytes; 116 } 118 119 123 private final static byte[] DECODABET = { 124 -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 155 }; 156 157 private final static byte BAD_ENCODING = -9; private final static byte WHITE_SPACE_ENC = -5; private final static byte EQUALS_SIGN_ENC = -1; 161 162 163 private Base64(){} 164 165 166 167 168 169 170 178 private static byte[] encode3to4( byte[] threeBytes ) { 179 return encode3to4( threeBytes, 3 ); 180 } 182 183 184 197 private static byte[] encode3to4( byte[] threeBytes, int numSigBytes ) { 198 byte[] dest = new byte[4]; 199 encode3to4( threeBytes, 0, numSigBytes, dest, 0 ); 200 return dest; 201 } 202 203 218 private static byte[] encode3to4( byte[] b4, byte[] threeBytes, int numSigBytes ) { 219 encode3to4( threeBytes, 0, numSigBytes, b4, 0 ); 220 return b4; 221 } 223 224 245 private static byte[] encode3to4( 246 byte[] source, int srcOffset, int numSigBytes, 247 byte[] destination, int destOffset ) { 248 255 int inBuff = ( numSigBytes > 0 ? ((source[ srcOffset ] << 24) >>> 8) : 0 ) 260 | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24) >>> 16) : 0 ) 261 | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24) >>> 24) : 0 ); 262 263 switch( numSigBytes ) { 264 case 3: 265 destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; 266 destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; 267 destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; 268 destination[ destOffset + 3 ] = ALPHABET[ (inBuff ) & 0x3f ]; 269 return destination; 270 271 case 2: 272 destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; 273 destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; 274 destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; 275 destination[ destOffset + 3 ] = EQUALS_SIGN; 276 return destination; 277 278 case 1: 279 destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; 280 destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; 281 destination[ destOffset + 2 ] = EQUALS_SIGN; 282 destination[ destOffset + 3 ] = EQUALS_SIGN; 283 return destination; 284 285 default: 286 return destination; 287 } } 290 291 292 303 public static String encodeObject( java.io.Serializable serializableObject ) { 304 return encodeObject( serializableObject, NO_OPTIONS ); 305 } 307 308 309 332 public static String encodeObject( java.io.Serializable serializableObject, int options ) { 333 java.io.ByteArrayOutputStream baos = null; 335 java.io.OutputStream b64os = null; 336 java.io.ObjectOutputStream oos = null; 337 java.util.zip.GZIPOutputStream gzos = null; 338 339 int gzip = (options & GZIP); 341 int dontBreakLines = (options & DONT_BREAK_LINES); 342 343 try { 344 baos = new java.io.ByteArrayOutputStream (); 346 b64os = new Base64.OutputStream( baos, ENCODE | dontBreakLines ); 347 348 if( gzip == GZIP ) { 350 gzos = new java.util.zip.GZIPOutputStream ( b64os ); 351 oos = new java.io.ObjectOutputStream ( gzos ); 352 } else 354 oos = new java.io.ObjectOutputStream ( b64os ); 355 356 oos.writeObject( serializableObject ); 357 } catch( java.io.IOException e ) { 359 e.printStackTrace(); 360 return null; 361 } finally { 363 try{ oos.close(); } catch( Exception e ){} 364 try{ gzos.close(); } catch( Exception e ){} 365 try{ b64os.close(); } catch( Exception e ){} 366 try{ baos.close(); } catch( Exception e ){} 367 } 369 try { 371 return new String ( baos.toByteArray(), PREFERRED_ENCODING ); 372 } catch (java.io.UnsupportedEncodingException uue) { 374 return new String ( baos.toByteArray() ); 375 } 377 } 379 380 381 388 public static String encodeBytes( byte[] source ) { 389 return encodeBytes( source, 0, source.length, NO_OPTIONS ); 390 } 392 393 394 414 public static String encodeBytes( byte[] source, int options ) { 415 return encodeBytes( source, 0, source.length, options ); 416 } 418 419 428 public static String encodeBytes( byte[] source, int off, int len ) { 429 return encodeBytes( source, off, len, NO_OPTIONS ); 430 } 432 433 434 457 public static String encodeBytes( byte[] source, int off, int len, int options ) { 458 int dontBreakLines = ( options & DONT_BREAK_LINES ); 460 int gzip = ( options & GZIP ); 461 462 if( gzip == GZIP ) { 464 java.io.ByteArrayOutputStream baos = null; 465 java.util.zip.GZIPOutputStream gzos = null; 466 Base64.OutputStream b64os = null; 467 468 469 try { 470 baos = new java.io.ByteArrayOutputStream (); 472 b64os = new Base64.OutputStream( baos, ENCODE | dontBreakLines ); 473 gzos = new java.util.zip.GZIPOutputStream ( b64os ); 474 475 gzos.write( source, off, len ); 476 gzos.close(); 477 } catch( java.io.IOException e ) { 479 e.printStackTrace(); 480 return null; 481 } finally { 483 try{ gzos.close(); } catch( Exception e ){} 484 try{ b64os.close(); } catch( Exception e ){} 485 try{ baos.close(); } catch( Exception e ){} 486 } 488 try { 490 return new String ( baos.toByteArray(), PREFERRED_ENCODING ); 491 } catch (java.io.UnsupportedEncodingException uue) { 493 return new String ( baos.toByteArray() ); 494 } } 497 else { 499 boolean breakLines = dontBreakLines == 0; 501 502 int len43 = len * 4 / 3; 503 byte[] outBuff = new byte[ ( len43 ) + ( (len % 3) > 0 ? 4 : 0 ) + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; int d = 0; 507 int e = 0; 508 int len2 = len - 2; 509 int lineLength = 0; 510 for( ; d < len2; d+=3, e+=4 ) { 511 encode3to4( source, d+off, 3, outBuff, e ); 512 513 lineLength += 4; 514 if( breakLines && lineLength == MAX_LINE_LENGTH ) { 515 outBuff[e+4] = NEW_LINE; 516 e++; 517 lineLength = 0; 518 } } 521 if( d < len ) { 522 encode3to4( source, d+off, len - d, outBuff, e ); 523 e += 4; 524 } 526 527 try { 529 return new String ( outBuff, 0, e, PREFERRED_ENCODING ); 530 } catch (java.io.UnsupportedEncodingException uue) { 532 return new String ( outBuff, 0, e ); 533 } 535 } 537 } 539 540 541 542 543 544 545 546 555 private static byte[] decode4to3( byte[] fourBytes ) { 556 byte[] outBuff1 = new byte[3]; 557 int count = decode4to3( fourBytes, 0, outBuff1, 0 ); 558 byte[] outBuff2 = new byte[ count ]; 559 560 for( int i = 0; i < count; i++ ) 561 outBuff2[i] = outBuff1[i]; 562 563 return outBuff2; 564 } 565 566 567 568 569 591 private static int decode4to3( byte[] source, int srcOffset, byte[] destination, int destOffset ) { 592 if( source[ srcOffset + 2] == EQUALS_SIGN ) { 594 int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) 598 | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF ) << 12 ); 599 600 destination[ destOffset ] = (byte)( outBuff >>> 16 ); 601 return 1; 602 } 603 604 else if( source[ srcOffset + 3 ] == EQUALS_SIGN ) { 606 int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) 611 | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) 612 | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6 ); 613 614 destination[ destOffset ] = (byte)( outBuff >>> 16 ); 615 destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 ); 616 return 2; 617 } 618 619 else { 621 try{ 622 int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) 628 | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) 629 | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6) 630 | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF ) ); 631 632 633 destination[ destOffset ] = (byte)( outBuff >> 16 ); 634 destination[ destOffset + 1 ] = (byte)( outBuff >> 8 ); 635 destination[ destOffset + 2 ] = (byte)( outBuff ); 636 637 return 3; 638 }catch( Exception e){ 639 System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset ] ] ) ); 640 System.out.println(""+source[srcOffset+1]+ ": " + ( DECODABET[ source[ srcOffset + 1 ] ] ) ); 641 System.out.println(""+source[srcOffset+2]+ ": " + ( DECODABET[ source[ srcOffset + 2 ] ] ) ); 642 System.out.println(""+source[srcOffset+3]+ ": " + ( DECODABET[ source[ srcOffset + 3 ] ] ) ); 643 return -1; 644 } } 646 } 648 649 650 651 662 public static byte[] decode( byte[] source, int off, int len ) { 663 int len34 = len * 3 / 4; 664 byte[] outBuff = new byte[ len34 ]; int outBuffPosn = 0; 666 667 byte[] b4 = new byte[4]; 668 int b4Posn = 0; 669 int i = 0; 670 byte sbiCrop = 0; 671 byte sbiDecode = 0; 672 for( i = off; i < off+len; i++ ) { 673 sbiCrop = (byte)(source[i] & 0x7f); sbiDecode = DECODABET[ sbiCrop ]; 675 676 if( sbiDecode >= WHITE_SPACE_ENC ) { 678 if( sbiDecode >= EQUALS_SIGN_ENC ) { 679 b4[ b4Posn++ ] = sbiCrop; 680 if( b4Posn > 3 ) { 681 outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn ); 682 b4Posn = 0; 683 684 if( sbiCrop == EQUALS_SIGN ) 686 break; 687 } 689 } 691 } else { 693 System.err.println( "Bad Base64 input character at " + i + ": " + source[i] + "(decimal)" ); 694 return null; 695 } } 698 byte[] out = new byte[ outBuffPosn ]; 699 System.arraycopy( outBuff, 0, out, 0, outBuffPosn ); 700 return out; 701 } 703 704 705 706 714 public static byte[] decode( String s ) { 715 byte[] bytes; 716 try { 717 bytes = s.getBytes( PREFERRED_ENCODING ); 718 } catch( java.io.UnsupportedEncodingException uee ) { 720 bytes = s.getBytes(); 721 } 724 bytes = decode( bytes, 0, bytes.length ); 726 727 728 if( bytes.length >= 2 ) { 731 732 int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); 733 if( 734 bytes != null && bytes.length >= 4 && java.util.zip.GZIPInputStream.GZIP_MAGIC == head ) { 737 java.io.ByteArrayInputStream bais = null; 738 java.util.zip.GZIPInputStream gzis = null; 739 java.io.ByteArrayOutputStream baos = null; 740 byte[] buffer = new byte[2048]; 741 int length = 0; 742 743 try { 744 baos = new java.io.ByteArrayOutputStream (); 745 bais = new java.io.ByteArrayInputStream ( bytes ); 746 gzis = new java.util.zip.GZIPInputStream ( bais ); 747 748 while( ( length = gzis.read( buffer ) ) >= 0 ) { 749 baos.write(buffer,0,length); 750 } 752 bytes = baos.toByteArray(); 754 755 } catch( java.io.IOException e ) { 757 } finally { 760 try{ baos.close(); } catch( Exception e ){} 761 try{ gzis.close(); } catch( Exception e ){} 762 try{ bais.close(); } catch( Exception e ){} 763 } 765 } } 768 return bytes; 769 } 771 772 773 774 782 public static Object decodeToObject( String encodedObject ) { 783 byte[] objBytes = decode( encodedObject ); 785 786 java.io.ByteArrayInputStream bais = null; 787 java.io.ObjectInputStream ois = null; 788 Object obj = null; 789 790 try { 791 bais = new java.io.ByteArrayInputStream ( objBytes ); 792 ois = new java.io.ObjectInputStream ( bais ); 793 794 obj = ois.readObject(); 795 } catch( java.io.IOException e ) { 797 e.printStackTrace(); 798 obj = null; 799 } catch( java.lang.ClassNotFoundException e ) { 801 e.printStackTrace(); 802 obj = null; 803 } finally { 805 try{ bais.close(); } catch( Exception e ){} 806 try{ ois.close(); } catch( Exception e ){} 807 } 809 return obj; 810 } 812 813 814 815 816 817 826 public static class InputStream extends java.io.FilterInputStream { 827 private int options; private boolean encode; private int position; private byte[] buffer; private int bufferLength; private int numSigBytes; private int lineLength; 834 private boolean breakLines; 836 837 843 public InputStream( java.io.InputStream in ) { 844 this( in, DECODE ); 845 } 847 848 869 public InputStream( java.io.InputStream in, int options ) { 870 super( in ); 871 this.options = options; 872 this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES; 873 this.encode = (options & ENCODE) == ENCODE; 874 this.bufferLength = encode ? 4 : 3; 875 this.buffer = new byte[ bufferLength ]; 876 this.position = -1; 877 this.lineLength = 0; 878 } 880 887 public int read() throws java.io.IOException { 888 if( position < 0 ) { 890 if( encode ) { 891 byte[] b3 = new byte[3]; 892 int numBinaryBytes = 0; 893 for( int i = 0; i < 3; i++ ) { 894 try { 895 int b = in.read(); 896 897 if( b >= 0 ) { 899 b3[i] = (byte)b; 900 numBinaryBytes++; 901 } 903 } catch( java.io.IOException e ) { 905 if( i == 0 ) 907 throw e; 908 909 } } 912 if( numBinaryBytes > 0 ) { 913 encode3to4( b3, 0, numBinaryBytes, buffer, 0 ); 914 position = 0; 915 numSigBytes = 4; 916 } else { 918 return -1; 919 } } 922 else { 924 byte[] b4 = new byte[4]; 925 int i = 0; 926 for( i = 0; i < 4; i++ ) { 927 int b = 0; 929 do{ b = in.read(); } 930 while( b >= 0 && DECODABET[ b & 0x7f ] <= WHITE_SPACE_ENC ); 931 932 if( b < 0 ) 933 break; 935 b4[i] = (byte)b; 936 } 938 if( i == 4 ) { 939 numSigBytes = decode4to3( b4, 0, buffer, 0 ); 940 position = 0; 941 } else if( i == 0 ){ 943 return -1; 944 } else { 946 throw new java.io.IOException ( "Improperly padded Base64 input." ); 948 } 950 } } 953 if( position >= 0 ) { 955 if( position >= numSigBytes ) 957 return -1; 958 959 if( encode && breakLines && lineLength >= MAX_LINE_LENGTH ) { 960 lineLength = 0; 961 return '\n'; 962 } else { 964 lineLength++; 968 int b = buffer[ position++ ]; 969 970 if( position >= bufferLength ) 971 position = -1; 972 973 return b & 0xFF; } } 978 else { 980 throw new java.io.IOException ( "Error in Base64 code reading stream." ); 982 } } 985 986 998 public int read( byte[] dest, int off, int len ) throws java.io.IOException { 999 int i; 1000 int b; 1001 for( i = 0; i < len; i++ ) { 1002 b = read(); 1003 1004 1007 if( b >= 0 ) 1008 dest[off + i] = (byte)b; 1009 else if( i == 0 ) 1010 return -1; 1011 else 1012 break; } return i; 1015 } 1017 } 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1037 public static class OutputStream extends java.io.FilterOutputStream { 1038 private int options; 1039 private boolean encode; 1040 private int position; 1041 private byte[] buffer; 1042 private int bufferLength; 1043 private int lineLength; 1044 private boolean breakLines; 1045 private byte[] b4; private boolean suspendEncoding; 1047 1048 1054 public OutputStream( java.io.OutputStream out ) { 1055 this( out, ENCODE ); 1056 } 1058 1059 1079 public OutputStream( java.io.OutputStream out, int options ) { 1080 super( out ); 1081 this.options = options; 1082 this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES; 1083 this.encode = (options & ENCODE) == ENCODE; 1084 this.bufferLength = encode ? 3 : 4; 1085 this.buffer = new byte[ bufferLength ]; 1086 this.position = 0; 1087 this.lineLength = 0; 1088 this.suspendEncoding = false; 1089 this.b4 = new byte[4]; 1090 } 1092 1093 1105 public void write(int theByte) throws java.io.IOException { 1106 if( suspendEncoding ) { 1108 super.out.write( theByte ); 1109 return; 1110 } 1112 if( encode ) { 1114 buffer[ position++ ] = (byte)theByte; 1115 if( position >= bufferLength ) { 1117 out.write( encode3to4( b4, buffer, bufferLength ) ); 1118 1119 lineLength += 4; 1120 if( breakLines && lineLength >= MAX_LINE_LENGTH ) { 1121 out.write( NEW_LINE ); 1122 lineLength = 0; 1123 } 1125 position = 0; 1126 } } 1129 else { 1131 if( DECODABET[ theByte & 0x7f ] > WHITE_SPACE_ENC ) { 1133 buffer[ position++ ] = (byte)theByte; 1134 if( position >= bufferLength ) { 1136 int len = Base64.decode4to3( buffer, 0, b4, 0 ); 1137 out.write( b4, 0, len ); 1138 position = 0; 1140 } } else if( DECODABET[ theByte & 0x7f ] != WHITE_SPACE_ENC ) { 1143 throw new java.io.IOException ( "Invalid character in Base64 data." ); 1144 } } } 1148 1149 1150 1159 public void write( byte[] theBytes, int off, int len ) throws java.io.IOException { 1160 if( suspendEncoding ) { 1162 super.out.write( theBytes, off, len ); 1163 return; 1164 } 1166 for( int i = 0; i < len; i++ ) { 1167 write( theBytes[ off + i ] ); 1168 } 1170 } 1172 1173 1174 1178 public void flushBase64() throws java.io.IOException { 1179 if( position > 0 ) { 1180 if( encode ) { 1181 out.write( encode3to4( b4, buffer, position ) ); 1182 position = 0; 1183 } else { 1185 throw new java.io.IOException ( "Base64 input not properly padded." ); 1186 } } 1189 } 1191 1192 1197 public void close() throws java.io.IOException { 1198 flushBase64(); 1200 1201 super.close(); 1204 1205 buffer = null; 1206 out = null; 1207 } 1209 1210 1211 1218 public void suspendEncoding() throws java.io.IOException { 1219 flushBase64(); 1220 this.suspendEncoding = true; 1221 } 1223 1224 1231 public void resumeEncoding() { 1232 this.suspendEncoding = false; 1233 } 1235 1236 1237 } 1239 1240} | Popular Tags |