1 46 package org.drftpd.slave.socket; 47 48 public class Base64 49 { 50 51 52 53 54 55 public final static int NO_OPTIONS = 0; 56 57 58 public final static int ENCODE = 1; 59 60 61 62 public final static int DECODE = 0; 63 64 65 66 public final static int GZIP = 2; 67 68 69 70 public final static int DONT_BREAK_LINES = 8; 71 72 73 74 75 76 77 private final static int MAX_LINE_LENGTH = 76; 78 79 80 81 private final static byte EQUALS_SIGN = (byte)'='; 82 83 84 85 private final static byte NEW_LINE = (byte)'\n'; 86 87 88 89 private final static String PREFERRED_ENCODING = "UTF-8"; 90 91 92 93 private final static byte[] ALPHABET; 94 private final static byte[] _NATIVE_ALPHABET = 95 { 96 (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', 97 (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', 98 (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', 99 (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', 100 (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', 101 (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', 102 (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', 103 (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', 104 (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', 105 (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/' 106 }; 107 108 109 static 110 { 111 byte[] __bytes; 112 try 113 { 114 __bytes = new String ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/").getBytes( PREFERRED_ENCODING ); 115 } catch (java.io.UnsupportedEncodingException use) 117 { 118 __bytes = _NATIVE_ALPHABET; } ALPHABET = __bytes; 121 } 123 124 128 private final static byte[] DECODABET = 129 { 130 -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 161 }; 162 163 private final static byte BAD_ENCODING = -9; private final static byte WHITE_SPACE_ENC = -5; private final static byte EQUALS_SIGN_ENC = -1; 167 168 169 private Base64(){} 170 171 172 173 174 175 176 184 private static byte[] encode3to4( byte[] threeBytes ) 185 { 186 return encode3to4( threeBytes, 3 ); 187 } 189 190 191 204 private static byte[] encode3to4( byte[] threeBytes, int numSigBytes ) 205 { 206 byte[] dest = new byte[4]; 207 encode3to4( threeBytes, 0, numSigBytes, dest, 0 ); 208 return dest; 209 } 210 211 226 private static byte[] encode3to4( byte[] b4, byte[] threeBytes, int numSigBytes ) 227 { 228 encode3to4( threeBytes, 0, numSigBytes, b4, 0 ); 229 return b4; 230 } 232 233 254 private static byte[] encode3to4( 255 byte[] source, int srcOffset, int numSigBytes, 256 byte[] destination, int destOffset ) 257 { 258 265 int inBuff = ( numSigBytes > 0 ? ((source[ srcOffset ] << 24) >>> 8) : 0 ) 270 | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24) >>> 16) : 0 ) 271 | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24) >>> 24) : 0 ); 272 273 switch( numSigBytes ) 274 { 275 case 3: 276 destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; 277 destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; 278 destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; 279 destination[ destOffset + 3 ] = ALPHABET[ (inBuff ) & 0x3f ]; 280 return destination; 281 282 case 2: 283 destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; 284 destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; 285 destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; 286 destination[ destOffset + 3 ] = EQUALS_SIGN; 287 return destination; 288 289 case 1: 290 destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; 291 destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; 292 destination[ destOffset + 2 ] = EQUALS_SIGN; 293 destination[ destOffset + 3 ] = EQUALS_SIGN; 294 return destination; 295 296 default: 297 return destination; 298 } } 301 302 303 314 public static String encodeObject( java.io.Serializable serializableObject ) 315 { 316 return encodeObject( serializableObject, NO_OPTIONS ); 317 } 319 320 321 344 public static String encodeObject( java.io.Serializable serializableObject, int options ) 345 { 346 java.io.ByteArrayOutputStream baos = null; 348 java.io.OutputStream b64os = null; 349 java.io.ObjectOutputStream oos = null; 350 java.util.zip.GZIPOutputStream gzos = null; 351 352 int gzip = (options & GZIP); 354 int dontBreakLines = (options & DONT_BREAK_LINES); 355 356 try 357 { 358 baos = new java.io.ByteArrayOutputStream (); 360 b64os = new Base64.OutputStream( baos, ENCODE | dontBreakLines ); 361 362 if( gzip == GZIP ) 364 { 365 gzos = new java.util.zip.GZIPOutputStream ( b64os ); 366 oos = new java.io.ObjectOutputStream ( gzos ); 367 } else 369 oos = new java.io.ObjectOutputStream ( b64os ); 370 371 oos.writeObject( serializableObject ); 372 } catch( java.io.IOException e ) 374 { 375 e.printStackTrace(); 376 return null; 377 } finally 379 { 380 try{ oos.close(); } catch( Exception e ){} 381 try{ gzos.close(); } catch( Exception e ){} 382 try{ b64os.close(); } catch( Exception e ){} 383 try{ baos.close(); } catch( Exception e ){} 384 } 386 try 388 { 389 return new String ( baos.toByteArray(), PREFERRED_ENCODING ); 390 } catch (java.io.UnsupportedEncodingException uue) 392 { 393 return new String ( baos.toByteArray() ); 394 } 396 } 398 399 400 407 public static String encodeBytes( byte[] source ) 408 { 409 return encodeBytes( source, 0, source.length, NO_OPTIONS ); 410 } 412 413 414 434 public static String encodeBytes( byte[] source, int options ) 435 { 436 return encodeBytes( source, 0, source.length, options ); 437 } 439 440 449 public static String encodeBytes( byte[] source, int off, int len ) 450 { 451 return encodeBytes( source, off, len, NO_OPTIONS ); 452 } 454 455 456 479 public static String encodeBytes( byte[] source, int off, int len, int options ) 480 { 481 int dontBreakLines = ( options & DONT_BREAK_LINES ); 483 int gzip = ( options & GZIP ); 484 485 if( gzip == GZIP ) 487 { 488 java.io.ByteArrayOutputStream baos = null; 489 java.util.zip.GZIPOutputStream gzos = null; 490 Base64.OutputStream b64os = null; 491 492 493 try 494 { 495 baos = new java.io.ByteArrayOutputStream (); 497 b64os = new Base64.OutputStream( baos, ENCODE | dontBreakLines ); 498 gzos = new java.util.zip.GZIPOutputStream ( b64os ); 499 500 gzos.write( source, off, len ); 501 gzos.close(); 502 } catch( java.io.IOException e ) 504 { 505 e.printStackTrace(); 506 return null; 507 } finally 509 { 510 try{ gzos.close(); } catch( Exception e ){} 511 try{ b64os.close(); } catch( Exception e ){} 512 try{ baos.close(); } catch( Exception e ){} 513 } 515 try 517 { 518 return new String ( baos.toByteArray(), PREFERRED_ENCODING ); 519 } catch (java.io.UnsupportedEncodingException uue) 521 { 522 return new String ( baos.toByteArray() ); 523 } } 526 else 528 { 529 boolean breakLines = dontBreakLines == 0; 531 532 int len43 = len * 4 / 3; 533 byte[] outBuff = new byte[ ( len43 ) + ( (len % 3) > 0 ? 4 : 0 ) + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; int d = 0; 537 int e = 0; 538 int len2 = len - 2; 539 int lineLength = 0; 540 for( ; d < len2; d+=3, e+=4 ) 541 { 542 encode3to4( source, d+off, 3, outBuff, e ); 543 544 lineLength += 4; 545 if( breakLines && lineLength == MAX_LINE_LENGTH ) 546 { 547 outBuff[e+4] = NEW_LINE; 548 e++; 549 lineLength = 0; 550 } } 553 if( d < len ) 554 { 555 encode3to4( source, d+off, len - d, outBuff, e ); 556 e += 4; 557 } 559 560 try 562 { 563 return new String ( outBuff, 0, e, PREFERRED_ENCODING ); 564 } catch (java.io.UnsupportedEncodingException uue) 566 { 567 return new String ( outBuff, 0, e ); 568 } 570 } 572 } 574 575 576 577 578 579 580 581 590 private static byte[] decode4to3( byte[] fourBytes ) 591 { 592 byte[] outBuff1 = new byte[3]; 593 int count = decode4to3( fourBytes, 0, outBuff1, 0 ); 594 byte[] outBuff2 = new byte[ count ]; 595 596 for( int i = 0; i < count; i++ ) 597 outBuff2[i] = outBuff1[i]; 598 599 return outBuff2; 600 } 601 602 603 604 605 627 private static int decode4to3( byte[] source, int srcOffset, byte[] destination, int destOffset ) 628 { 629 if( source[ srcOffset + 2] == EQUALS_SIGN ) 631 { 632 int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) 636 | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF ) << 12 ); 637 638 destination[ destOffset ] = (byte)( outBuff >>> 16 ); 639 return 1; 640 } 641 642 else if( source[ srcOffset + 3 ] == EQUALS_SIGN ) 644 { 645 int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) 650 | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) 651 | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6 ); 652 653 destination[ destOffset ] = (byte)( outBuff >>> 16 ); 654 destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 ); 655 return 2; 656 } 657 658 else 660 { 661 try{ 662 int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) 668 | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) 669 | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6) 670 | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF ) ); 671 672 673 destination[ destOffset ] = (byte)( outBuff >> 16 ); 674 destination[ destOffset + 1 ] = (byte)( outBuff >> 8 ); 675 destination[ destOffset + 2 ] = (byte)( outBuff ); 676 677 return 3; 678 }catch( Exception e){ 679 System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset ] ] ) ); 680 System.out.println(""+source[srcOffset+1]+ ": " + ( DECODABET[ source[ srcOffset + 1 ] ] ) ); 681 System.out.println(""+source[srcOffset+2]+ ": " + ( DECODABET[ source[ srcOffset + 2 ] ] ) ); 682 System.out.println(""+source[srcOffset+3]+ ": " + ( DECODABET[ source[ srcOffset + 3 ] ] ) ); 683 return -1; 684 } } 686 } 688 689 690 691 702 public static byte[] decode( byte[] source, int off, int len ) 703 { 704 int len34 = len * 3 / 4; 705 byte[] outBuff = new byte[ len34 ]; int outBuffPosn = 0; 707 708 byte[] b4 = new byte[4]; 709 int b4Posn = 0; 710 int i = 0; 711 byte sbiCrop = 0; 712 byte sbiDecode = 0; 713 for( i = off; i < off+len; i++ ) 714 { 715 sbiCrop = (byte)(source[i] & 0x7f); sbiDecode = DECODABET[ sbiCrop ]; 717 718 if( sbiDecode >= WHITE_SPACE_ENC ) { 720 if( sbiDecode >= EQUALS_SIGN_ENC ) 721 { 722 b4[ b4Posn++ ] = sbiCrop; 723 if( b4Posn > 3 ) 724 { 725 outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn ); 726 b4Posn = 0; 727 728 if( sbiCrop == EQUALS_SIGN ) 730 break; 731 } 733 } 735 } else 737 { 738 System.err.println( "Bad Base64 input character at " + i + ": " + source[i] + "(decimal)" ); 739 return null; 740 } } 743 byte[] out = new byte[ outBuffPosn ]; 744 System.arraycopy( outBuff, 0, out, 0, outBuffPosn ); 745 return out; 746 } 748 749 750 751 759 public static byte[] decode( String s ) 760 { 761 byte[] bytes; 762 try 763 { 764 bytes = s.getBytes( PREFERRED_ENCODING ); 765 } catch( java.io.UnsupportedEncodingException uee ) 767 { 768 bytes = s.getBytes(); 769 } 772 bytes = decode( bytes, 0, bytes.length ); 774 775 776 if( bytes.length >= 2 ) 779 { 780 781 int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); 782 if( 783 bytes != null && bytes.length >= 4 && java.util.zip.GZIPInputStream.GZIP_MAGIC == head ) 786 { 787 java.io.ByteArrayInputStream bais = null; 788 java.util.zip.GZIPInputStream gzis = null; 789 java.io.ByteArrayOutputStream baos = null; 790 byte[] buffer = new byte[2048]; 791 int length = 0; 792 793 try 794 { 795 baos = new java.io.ByteArrayOutputStream (); 796 bais = new java.io.ByteArrayInputStream ( bytes ); 797 gzis = new java.util.zip.GZIPInputStream ( bais ); 798 799 while( ( length = gzis.read( buffer ) ) >= 0 ) 800 { 801 baos.write(buffer,0,length); 802 } 804 bytes = baos.toByteArray(); 806 807 } catch( java.io.IOException e ) 809 { 810 } finally 813 { 814 try{ baos.close(); } catch( Exception e ){} 815 try{ gzis.close(); } catch( Exception e ){} 816 try{ bais.close(); } catch( Exception e ){} 817 } 819 } } 822 return bytes; 823 } 825 826 827 828 836 public static Object decodeToObject( String encodedObject ) 837 { 838 byte[] objBytes = decode( encodedObject ); 840 841 java.io.ByteArrayInputStream bais = null; 842 java.io.ObjectInputStream ois = null; 843 Object obj = null; 844 845 try 846 { 847 bais = new java.io.ByteArrayInputStream ( objBytes ); 848 ois = new java.io.ObjectInputStream ( bais ); 849 850 obj = ois.readObject(); 851 } catch( java.io.IOException e ) 853 { 854 e.printStackTrace(); 855 obj = null; 856 } catch( java.lang.ClassNotFoundException e ) 858 { 859 e.printStackTrace(); 860 obj = null; 861 } finally 863 { 864 try{ bais.close(); } catch( Exception e ){} 865 try{ ois.close(); } catch( Exception e ){} 866 } 868 return obj; 869 } 871 872 873 874 875 876 885 public static class InputStream extends java.io.FilterInputStream 886 { 887 private int options; private boolean encode; private int position; private byte[] buffer; private int bufferLength; private int numSigBytes; private int lineLength; 894 private boolean breakLines; 896 897 903 public InputStream( java.io.InputStream in ) 904 { 905 this( in, DECODE ); 906 } 908 909 930 public InputStream( java.io.InputStream in, int options ) 931 { 932 super( in ); 933 this.options = options; 934 this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES; 935 this.encode = (options & ENCODE) == ENCODE; 936 this.bufferLength = encode ? 4 : 3; 937 this.buffer = new byte[ bufferLength ]; 938 this.position = -1; 939 this.lineLength = 0; 940 } 942 949 public int read() throws java.io.IOException 950 { 951 if( position < 0 ) 953 { 954 if( encode ) 955 { 956 byte[] b3 = new byte[3]; 957 int numBinaryBytes = 0; 958 for( int i = 0; i < 3; i++ ) 959 { 960 try 961 { 962 int b = in.read(); 963 964 if( b >= 0 ) 966 { 967 b3[i] = (byte)b; 968 numBinaryBytes++; 969 } 971 } catch( java.io.IOException e ) 973 { 974 if( i == 0 ) 976 throw e; 977 978 } } 981 if( numBinaryBytes > 0 ) 982 { 983 encode3to4( b3, 0, numBinaryBytes, buffer, 0 ); 984 position = 0; 985 numSigBytes = 4; 986 } else 988 { 989 return -1; 990 } } 993 else 995 { 996 byte[] b4 = new byte[4]; 997 int i = 0; 998 for( i = 0; i < 4; i++ ) 999 { 1000 int b = 0; 1002 do{ b = in.read(); } 1003 while( b >= 0 && DECODABET[ b & 0x7f ] <= WHITE_SPACE_ENC ); 1004 1005 if( b < 0 ) 1006 break; 1008 b4[i] = (byte)b; 1009 } 1011 if( i == 4 ) 1012 { 1013 numSigBytes = decode4to3( b4, 0, buffer, 0 ); 1014 position = 0; 1015 } else if( i == 0 ){ 1017 return -1; 1018 } else 1020 { 1021 throw new java.io.IOException ( "Improperly padded Base64 input." ); 1023 } 1025 } } 1028 if( position >= 0 ) 1030 { 1031 if( position >= numSigBytes ) 1033 return -1; 1034 1035 if( encode && breakLines && lineLength >= MAX_LINE_LENGTH ) 1036 { 1037 lineLength = 0; 1038 return '\n'; 1039 } else 1041 { 1042 lineLength++; 1046 int b = buffer[ position++ ]; 1047 1048 if( position >= bufferLength ) 1049 position = -1; 1050 1051 return b & 0xFF; } } 1056 else 1058 { 1059 throw new java.io.IOException ( "Error in Base64 code reading stream." ); 1061 } } 1064 1065 1077 public int read( byte[] dest, int off, int len ) throws java.io.IOException 1078 { 1079 int i; 1080 int b; 1081 for( i = 0; i < len; i++ ) 1082 { 1083 b = read(); 1084 1085 1088 if( b >= 0 ) 1089 dest[off + i] = (byte)b; 1090 else if( i == 0 ) 1091 return -1; 1092 else 1093 break; } return i; 1096 } 1098 } 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1118 public static class OutputStream extends java.io.FilterOutputStream 1119 { 1120 private int options; 1121 private boolean encode; 1122 private int position; 1123 private byte[] buffer; 1124 private int bufferLength; 1125 private int lineLength; 1126 private boolean breakLines; 1127 private byte[] b4; private boolean suspendEncoding; 1129 1130 1136 public OutputStream( java.io.OutputStream out ) 1137 { 1138 this( out, ENCODE ); 1139 } 1141 1142 1162 public OutputStream( java.io.OutputStream out, int options ) 1163 { 1164 super( out ); 1165 this.options = options; 1166 this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES; 1167 this.encode = (options & ENCODE) == ENCODE; 1168 this.bufferLength = encode ? 3 : 4; 1169 this.buffer = new byte[ bufferLength ]; 1170 this.position = 0; 1171 this.lineLength = 0; 1172 this.suspendEncoding = false; 1173 this.b4 = new byte[4]; 1174 } 1176 1177 1189 public void write(int theByte) throws java.io.IOException 1190 { 1191 if( suspendEncoding ) 1193 { 1194 super.out.write( theByte ); 1195 return; 1196 } 1198 if( encode ) 1200 { 1201 buffer[ position++ ] = (byte)theByte; 1202 if( position >= bufferLength ) { 1204 out.write( encode3to4( b4, buffer, bufferLength ) ); 1205 1206 lineLength += 4; 1207 if( breakLines && lineLength >= MAX_LINE_LENGTH ) 1208 { 1209 out.write( NEW_LINE ); 1210 lineLength = 0; 1211 } 1213 position = 0; 1214 } } 1217 else 1219 { 1220 if( DECODABET[ theByte & 0x7f ] > WHITE_SPACE_ENC ) 1222 { 1223 buffer[ position++ ] = (byte)theByte; 1224 if( position >= bufferLength ) { 1226 int len = Base64.decode4to3( buffer, 0, b4, 0 ); 1227 out.write( b4, 0, len ); 1228 position = 0; 1230 } } else if( DECODABET[ theByte & 0x7f ] != WHITE_SPACE_ENC ) 1233 { 1234 throw new java.io.IOException ( "Invalid character in Base64 data." ); 1235 } } } 1239 1240 1241 1250 public void write( byte[] theBytes, int off, int len ) throws java.io.IOException 1251 { 1252 if( suspendEncoding ) 1254 { 1255 super.out.write( theBytes, off, len ); 1256 return; 1257 } 1259 for( int i = 0; i < len; i++ ) 1260 { 1261 write( theBytes[ off + i ] ); 1262 } 1264 } 1266 1267 1268 1272 public void flushBase64() throws java.io.IOException 1273 { 1274 if( position > 0 ) 1275 { 1276 if( encode ) 1277 { 1278 out.write( encode3to4( b4, buffer, position ) ); 1279 position = 0; 1280 } else 1282 { 1283 throw new java.io.IOException ( "Base64 input not properly padded." ); 1284 } } 1287 } 1289 1290 1295 public void close() throws java.io.IOException 1296 { 1297 flushBase64(); 1299 1300 super.close(); 1303 1304 buffer = null; 1305 out = null; 1306 } 1308 1309 1310 1317 public void suspendEncoding() throws java.io.IOException 1318 { 1319 flushBase64(); 1320 this.suspendEncoding = true; 1321 } 1323 1324 1331 public void resumeEncoding() 1332 { 1333 this.suspendEncoding = false; 1334 } 1336 1337 1338 } 1340 1341} | Popular Tags |