27
27
import java .io .UnsupportedEncodingException ;
28
28
import java .io .Writer ;
29
29
30
+ import static org .codehaus .groovy .runtime .EncodingGroovyMethodsSupport .TRANSLATE_TABLE ;
31
+ import static org .codehaus .groovy .runtime .EncodingGroovyMethodsSupport .TRANSLATE_TABLE_URLSAFE ;
32
+
30
33
/**
31
34
* This class defines all the encoding/decoding groovy methods which enhance
32
35
* the normal JDK classes when inside the Groovy environment.
@@ -36,6 +39,8 @@ public class EncodingGroovyMethods {
36
39
37
40
private static final char [] T_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" .toCharArray ();
38
41
42
+ private static final char [] T_TABLE_URLSAFE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=" .toCharArray ();
43
+
39
44
private static final String CHUNK_SEPARATOR = "\r \n " ;
40
45
41
46
/**
@@ -76,18 +81,22 @@ public static Writable encodeBase64(Byte[] data) {
76
81
* @since 1.5.7
77
82
*/
78
83
public static Writable encodeBase64 (final byte [] data , final boolean chunked ) {
84
+ return encodeBase64 (data , chunked , false , true );
85
+ }
86
+
87
+ private static Writable encodeBase64 (final byte [] data , final boolean chunked , final boolean urlSafe , final boolean pad ) {
79
88
return new Writable () {
80
89
public Writer writeTo (final Writer writer ) throws IOException {
81
90
int charCount = 0 ;
82
91
final int dLimit = (data .length / 3 ) * 3 ;
83
-
92
+ final char [] table = urlSafe ? T_TABLE_URLSAFE : T_TABLE ;
84
93
for (int dIndex = 0 ; dIndex != dLimit ; dIndex += 3 ) {
85
94
int d = ((data [dIndex ] & 0XFF ) << 16 ) | ((data [dIndex + 1 ] & 0XFF ) << 8 ) | (data [dIndex + 2 ] & 0XFF );
86
95
87
- writer .write (T_TABLE [d >> 18 ]);
88
- writer .write (T_TABLE [(d >> 12 ) & 0X3F ]);
89
- writer .write (T_TABLE [(d >> 6 ) & 0X3F ]);
90
- writer .write (T_TABLE [d & 0X3F ]);
96
+ writer .write (table [d >> 18 ]);
97
+ writer .write (table [(d >> 12 ) & 0X3F ]);
98
+ writer .write (table [(d >> 6 ) & 0X3F ]);
99
+ writer .write (table [d & 0X3F ]);
91
100
92
101
if (chunked && ++charCount == 19 ) {
93
102
writer .write (CHUNK_SEPARATOR );
@@ -102,10 +111,16 @@ public Writer writeTo(final Writer writer) throws IOException {
102
111
d |= (data [dLimit + 1 ] & 0XFF ) << 8 ;
103
112
}
104
113
105
- writer .write (T_TABLE [d >> 18 ]);
106
- writer .write (T_TABLE [(d >> 12 ) & 0X3F ]);
107
- writer .write ((dLimit + 1 < data .length ) ? T_TABLE [(d >> 6 ) & 0X3F ] : '=' );
108
- writer .write ('=' );
114
+ writer .write (table [d >> 18 ]);
115
+ writer .write (table [(d >> 12 ) & 0X3F ]);
116
+ if (pad ) {
117
+ writer .write ((dLimit + 1 < data .length ) ? table [(d >> 6 ) & 0X3F ] : '=' );
118
+ writer .write ('=' );
119
+ } else {
120
+ if (dLimit + 1 < data .length ) {
121
+ writer .write (table [(d >> 6 ) & 0X3F ]);
122
+ }
123
+ }
109
124
if (chunked && charCount != 0 ) {
110
125
writer .write (CHUNK_SEPARATOR );
111
126
}
@@ -141,6 +156,74 @@ public static Writable encodeBase64(final byte[] data) {
141
156
return encodeBase64 (data , false );
142
157
}
143
158
159
+ /**
160
+ * Produce a Writable object which writes the Base64 URL and Filename Safe encoding of the byte array.
161
+ * Calling toString() on the result returns the encoding as a String. For more
162
+ * information on Base64 URL and Filename Safe encoding see <code>RFC 4648 - Section 5
163
+ * Base 64 Encoding with URL and Filename Safe Alphabet</code>.
164
+ * <p>
165
+ * The method omits padding and is equivalent to calling
166
+ * {@link org.codehaus.groovy.runtime.EncodingGroovyMethods#encodeBase64Url(Byte[], boolean)} with a
167
+ * value of {@code false}.
168
+ *
169
+ * @param data Byte array to be encoded
170
+ * @return object which will write the Base64 URL and Filename Safe encoding of the byte array
171
+ * @see org.codehaus.groovy.runtime.EncodingGroovyMethods#encodeBase64Url(Byte[], boolean)
172
+ * @since 2.5
173
+ */
174
+ public static Writable encodeBase64Url (Byte [] data ) {
175
+ return encodeBase64Url (data , false );
176
+ }
177
+
178
+ /**
179
+ * Produce a Writable object which writes the Base64 URL and Filename Safe encoding of the byte array.
180
+ * Calling toString() on the result returns the encoding as a String. For more
181
+ * information on Base64 URL and Filename Safe encoding see <code>RFC 4648 - Section 5
182
+ * Base 64 Encoding with URL and Filename Safe Alphabet</code>.
183
+ *
184
+ * @param data Byte array to be encoded
185
+ * @param pad whether or not the encoded data should be padded
186
+ * @return object which will write the Base64 URL and Filename Safe encoding of the byte array
187
+ * @since 2.5
188
+ */
189
+ public static Writable encodeBase64Url (Byte [] data , boolean pad ) {
190
+ return encodeBase64Url (DefaultTypeTransformation .convertToByteArray (data ), pad );
191
+ }
192
+
193
+ /**
194
+ * Produce a Writable object which writes the Base64 URL and Filename Safe encoding of the byte array.
195
+ * Calling toString() on the result returns the encoding as a String. For more
196
+ * information on Base64 URL and Filename Safe encoding see <code>RFC 4648 - Section 5
197
+ * Base 64 Encoding with URL and Filename Safe Alphabet</code>.
198
+ * <p>
199
+ * The method omits padding and is equivalent to calling
200
+ * {@link org.codehaus.groovy.runtime.EncodingGroovyMethods#encodeBase64Url(byte[], boolean)} with a
201
+ * value of {@code false}.
202
+ *
203
+ * @param data Byte array to be encoded
204
+ * @return object which will write the Base64 URL and Filename Safe encoding of the byte array
205
+ * @see org.codehaus.groovy.runtime.EncodingGroovyMethods#encodeBase64Url(byte[], boolean)
206
+ * @since 2.5
207
+ */
208
+ public static Writable encodeBase64Url (final byte [] data ) {
209
+ return encodeBase64Url (data , false );
210
+ }
211
+
212
+ /**
213
+ * Produce a Writable object which writes the Base64 URL and Filename Safe encoding of the byte array.
214
+ * Calling toString() on the result returns the encoding as a String. For more
215
+ * information on Base64 URL and Filename Safe encoding see <code>RFC 4648 - Section 5
216
+ * Base 64 Encoding with URL and Filename Safe Alphabet</code>.
217
+ *
218
+ * @param data Byte array to be encoded
219
+ * @param pad whether or not the encoded data should be padded
220
+ * @return object which will write the Base64 URL and Filename Safe encoding of the byte array
221
+ * @since 2.5
222
+ */
223
+ public static Writable encodeBase64Url (final byte [] data , final boolean pad ) {
224
+ return encodeBase64 (data , false , true , pad );
225
+ }
226
+
144
227
/**
145
228
* Decode the String from Base64 into a byte array.
146
229
*
@@ -149,14 +232,29 @@ public static Writable encodeBase64(final byte[] data) {
149
232
* @since 1.0
150
233
*/
151
234
public static byte [] decodeBase64 (String value ) {
235
+ return decodeBase64 (value , false );
236
+ }
237
+
238
+ /**
239
+ * Decodes a Base64 URL and Filename Safe encoded String into a byte array.
240
+ *
241
+ * @param value the string to be decoded
242
+ * @return the decoded bytes as an array
243
+ * @since 2.5
244
+ */
245
+ public static byte [] decodeBase64Url (String value ) {
246
+ return decodeBase64 (value , true );
247
+ }
248
+
249
+ private static byte [] decodeBase64 (String value , boolean urlSafe ) {
152
250
int byteShift = 4 ;
153
251
int tmp = 0 ;
154
252
boolean done = false ;
155
253
final StringBuilder buffer = new StringBuilder ();
156
-
254
+ final byte [] table = urlSafe ? TRANSLATE_TABLE_URLSAFE : TRANSLATE_TABLE ;
157
255
for (int i = 0 ; i != value .length (); i ++) {
158
256
final char c = value .charAt (i );
159
- final int sixBit = (c < 123 ) ? EncodingGroovyMethodsSupport . TRANSLATE_TABLE [c ] : 66 ;
257
+ final int sixBit = (c < 123 ) ? table [c ] : 66 ;
160
258
161
259
if (sixBit < 64 ) {
162
260
if (done )
0 commit comments