1
1
2
2
/**
3
3
* Copyright (C) 2012 10gen Inc.
4
- *
4
+ *
5
5
* Licensed under the Apache License, Version 2.0 (the "License");
6
6
* you may not use this file except in compliance with the License.
7
7
* You may obtain a copy of the License at
8
- *
8
+ *
9
9
* http://www.apache.org/licenses/LICENSE-2.0
10
- *
10
+ *
11
11
* Unless required by applicable law or agreed to in writing, software
12
12
* distributed under the License is distributed on an "AS IS" BASIS,
13
13
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35
35
36
36
/**
37
37
* Provides Base64 encoding and decoding </a>.
38
- *
38
+ * <p/>
39
39
* <p>
40
40
* This class implements Base64 encoding
41
- *
42
- * Thanks to Apache Commons project. This class refactored from org.apache.commons.codec.binary
43
- *
41
+ * <p/>
42
+ * Thanks to Apache Commons project. This class refactored from org.apache.commons.codec.binary
43
+ * <p/>
44
44
* Original Thanks to "commons" project in ws.apache.org for this code.
45
45
* http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
46
46
* </p>
47
- *
48
47
*/
49
48
public class Base64Codec {
50
-
51
- private static int BYTES_PER_UNENCODED_BLOCK = 3 ;
52
- private static int BYTES_PER_ENCODED_BLOCK = 4 ;
53
-
54
- /** Mask used to extract 6 bits, used when encoding */
55
- private static final int SixBitMask = 0x3f ;
56
-
57
- /** padding char */
49
+
50
+ private static final int BYTES_PER_UNENCODED_BLOCK = 3 ;
51
+ private static final int BYTES_PER_ENCODED_BLOCK = 4 ;
52
+
53
+ /**
54
+ * Mask used to extract 6 bits, used when encoding
55
+ */
56
+ private static final int SixBitMask = 0x3f ;
57
+
58
+ /**
59
+ * padding char
60
+ */
58
61
private static final byte PAD = '=' ;
59
-
62
+
60
63
/**
61
64
* This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet"
62
65
* equivalents as specified in Table 1 of RFC 2045.
63
- *
64
66
*/
65
- private static final byte [] EncodeTable = { 'A' , 'B' , 'C' , 'D' , 'E' , 'F' ,
67
+ private static final byte [] EncodeTable = {'A' , 'B' , 'C' , 'D' , 'E' , 'F' ,
66
68
'G' , 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' , 'S' ,
67
69
'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' ,
68
70
'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' ,
69
71
't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' , '0' , '1' , '2' , '3' , '4' , '5' ,
70
- '6' , '7' , '8' , '9' , '+' , '/' };
71
-
72
-
72
+ '6' , '7' , '8' , '9' , '+' , '/' };
73
+
74
+ private static final int [] DecodeTable = new int [128 ];
75
+
76
+ static {
77
+ for (int i = 0 ; i < EncodeTable .length ; i ++) {
78
+ DecodeTable [EncodeTable [i ]] = i ;
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Translates the specified Base64 string into a byte array.
84
+ *
85
+ * @param s the Base64 string (not null)
86
+ * @return the byte array (not null)
87
+ */
88
+ public byte [] decode (String s ) {
89
+ int delta = s .endsWith ("==" ) ? 2 : s .endsWith ("=" ) ? 1 : 0 ;
90
+ byte [] buffer = new byte [s .length () * BYTES_PER_UNENCODED_BLOCK / BYTES_PER_ENCODED_BLOCK - delta ];
91
+ int mask = 0xFF ;
92
+ int pos = 0 ;
93
+ for (int i = 0 ; i < s .length (); i += BYTES_PER_ENCODED_BLOCK ) {
94
+ int c0 = DecodeTable [s .charAt (i )];
95
+ int c1 = DecodeTable [s .charAt (i + 1 )];
96
+ buffer [pos ++] = (byte ) (((c0 << 2 ) | (c1 >> 4 )) & mask );
97
+ if (pos >= buffer .length ) {
98
+ return buffer ;
99
+ }
100
+ int c2 = DecodeTable [s .charAt (i + 2 )];
101
+ buffer [pos ++] = (byte ) (((c1 << 4 ) | (c2 >> 2 )) & mask );
102
+ if (pos >= buffer .length ) {
103
+ return buffer ;
104
+ }
105
+ int c3 = DecodeTable [s .charAt (i + 3 )];
106
+ buffer [pos ++] = (byte ) (((c2 << 6 ) | c3 ) & mask );
107
+ }
108
+ return buffer ;
109
+ }
110
+
111
+ /**
112
+ * Translates the specified byte array into Base64 string.
113
+ *
114
+ * @param in the byte array (not null)
115
+ * @return the translated Base64 string (not null)
116
+ */
73
117
public String encode (byte [] in ) {
74
-
118
+
75
119
int modulus = 0 ;
76
120
int bitWorkArea = 0 ;
77
- int numEncodedBytes = (in .length / BYTES_PER_UNENCODED_BLOCK )* BYTES_PER_ENCODED_BLOCK
78
- + ((in .length % BYTES_PER_UNENCODED_BLOCK == 0 )? 0 : 4 );
121
+ int numEncodedBytes = (in .length / BYTES_PER_UNENCODED_BLOCK ) * BYTES_PER_ENCODED_BLOCK
122
+ + ((in .length % BYTES_PER_UNENCODED_BLOCK == 0 ) ? 0 : 4 );
79
123
80
- byte [] buffer = new byte [numEncodedBytes ];
124
+ byte [] buffer = new byte [numEncodedBytes ];
81
125
int pos = 0 ;
82
-
83
- for (int i = 0 ; i < in .length ; i ++) {
84
- modulus = (modulus +1 ) % BYTES_PER_UNENCODED_BLOCK ;
85
- int b = in [i ];
86
-
87
- if (b < 0 )
126
+
127
+ for (int b : in ) {
128
+ modulus = (modulus + 1 ) % BYTES_PER_UNENCODED_BLOCK ;
129
+
130
+ if (b < 0 )
88
131
b += 256 ;
89
-
132
+
90
133
bitWorkArea = (bitWorkArea << 8 ) + b ; // BITS_PER_BYTE
91
134
if (0 == modulus ) { // 3 bytes = 24 bits = 4 * 6 bits to extract
92
135
buffer [pos ++] = EncodeTable [(bitWorkArea >> 18 ) & SixBitMask ];
@@ -95,23 +138,23 @@ public String encode(byte[] in) {
95
138
buffer [pos ++] = EncodeTable [bitWorkArea & SixBitMask ];
96
139
}
97
140
}
98
-
141
+
99
142
switch (modulus ) { // 0-2
100
- case 1 : // 8 bits = 6 + 2
101
- buffer [pos ++] = EncodeTable [(bitWorkArea >> 2 ) & SixBitMask ]; // top 6 bits
102
- buffer [pos ++] = EncodeTable [(bitWorkArea << 4 ) & SixBitMask ]; // remaining 2
103
- buffer [pos ++] = PAD ;
104
- buffer [pos ++ ] = PAD ;
105
- break ;
106
-
107
- case 2 : // 16 bits = 6 + 6 + 4
108
- buffer [pos ++] = EncodeTable [(bitWorkArea >> 10 ) & SixBitMask ];
109
- buffer [pos ++] = EncodeTable [(bitWorkArea >> 4 ) & SixBitMask ];
110
- buffer [pos ++] = EncodeTable [(bitWorkArea << 2 ) & SixBitMask ];
111
- buffer [pos ++ ] = PAD ;
112
- break ;
143
+ case 1 : // 8 bits = 6 + 2
144
+ buffer [pos ++] = EncodeTable [(bitWorkArea >> 2 ) & SixBitMask ]; // top 6 bits
145
+ buffer [pos ++] = EncodeTable [(bitWorkArea << 4 ) & SixBitMask ]; // remaining 2
146
+ buffer [pos ++] = PAD ;
147
+ buffer [pos ] = PAD ; // Last entry no need to ++
148
+ break ;
149
+
150
+ case 2 : // 16 bits = 6 + 6 + 4
151
+ buffer [pos ++] = EncodeTable [(bitWorkArea >> 10 ) & SixBitMask ];
152
+ buffer [pos ++] = EncodeTable [(bitWorkArea >> 4 ) & SixBitMask ];
153
+ buffer [pos ++] = EncodeTable [(bitWorkArea << 2 ) & SixBitMask ];
154
+ buffer [pos ] = PAD ; // Last entry no need to ++
155
+ break ;
113
156
}
114
-
157
+
115
158
return new String (buffer );
116
159
}
117
160
}
0 commit comments