1 // Copyright 2003-2010 Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland 2 // www.source-code.biz, www.inventec.ch/chdh 3 // 4 // This module is multi-licensed and may be used under the terms 5 // of any of the following licenses: 6 // 7 // EPL, Eclipse Public License, V1.0 or later, http://www.eclipse.org/legal 8 // LGPL, GNU Lesser General Public License, V2.1 or later, http://www.gnu.org/licenses/lgpl.html 9 // GPL, GNU General Public License, V2 or later, http://www.gnu.org/licenses/gpl.html 10 // AL, Apache License, V2.0 or later, http://www.apache.org/licenses 11 // BSD, BSD License, http://www.opensource.org/licenses/bsd-license.php 12 // 13 // Please contact the author if you need another license. 14 // This module is provided "as is", without warranties of any kind. 15 16 package org.yaml.snakeyaml.external.biz.base64Coder; 17 18 /** 19 * A Base64 encoder/decoder. 20 * 21 * <p> 22 * This class is used to encode and decode data in Base64 format as described in 23 * RFC 1521. 24 * 25 * <p> 26 * Project home page: <a 27 * href="http://www.source-code.biz/base64coder/java/">www. 28 * source-code.biz/base64coder/java</a><br> 29 * Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland<br> 30 * Multi-licensed: EPL / LGPL / GPL / AL / BSD. 31 */ 32 public class Base64Coder { 33 34 // The line separator string of the operating system. 35 private static final String systemLineSeparator = System.getProperty("line.separator"); 36 37 // Mapping table from 6-bit nibbles to Base64 characters. 38 private static char[] map1 = new char[64]; 39 static { 40 int i = 0; 41 for (char c = 'A'; c <= 'Z'; c++) 42 map1[i++] = c; 43 for (char c = 'a'; c <= 'z'; c++) 44 map1[i++] = c; 45 for (char c = '0'; c <= '9'; c++) 46 map1[i++] = c; 47 map1[i++] = '+'; 48 map1[i++] = '/'; 49 } 50 51 // Mapping table from Base64 characters to 6-bit nibbles. 52 private static byte[] map2 = new byte[128]; 53 static { 54 for (int i = 0; i < map2.length; i++) 55 map2[i] = -1; 56 for (int i = 0; i < 64; i++) 57 map2[map1[i]] = (byte) i; 58 } 59 60 /** 61 * Encodes a string into Base64 format. No blanks or line breaks are 62 * inserted. 63 * 64 * @param s 65 * A String to be encoded. 66 * @return A String containing the Base64 encoded data. 67 */ encodeString(String s)68 public static String encodeString(String s) { 69 return new String(encode(s.getBytes())); 70 } 71 72 /** 73 * Encodes a byte array into Base 64 format and breaks the output into lines 74 * of 76 characters. This method is compatible with 75 * <code>sun.misc.BASE64Encoder.encodeBuffer(byte[])</code>. 76 * 77 * @param in 78 * An array containing the data bytes to be encoded. 79 * @return A String containing the Base64 encoded data, broken into lines. 80 */ encodeLines(byte[] in)81 public static String encodeLines(byte[] in) { 82 return encodeLines(in, 0, in.length, 76, systemLineSeparator); 83 } 84 85 /** 86 * Encodes a byte array into Base 64 format and breaks the output into 87 * lines. 88 * 89 * @param in 90 * An array containing the data bytes to be encoded. 91 * @param iOff 92 * Offset of the first byte in <code>in</code> to be processed. 93 * @param iLen 94 * Number of bytes to be processed in <code>in</code>, starting 95 * at <code>iOff</code>. 96 * @param lineLen 97 * Line length for the output data. Should be a multiple of 4. 98 * @param lineSeparator 99 * The line separator to be used to separate the output lines. 100 * @return A String containing the Base64 encoded data, broken into lines. 101 */ encodeLines(byte[] in, int iOff, int iLen, int lineLen, String lineSeparator)102 public static String encodeLines(byte[] in, int iOff, int iLen, int lineLen, 103 String lineSeparator) { 104 int blockLen = (lineLen * 3) / 4; 105 if (blockLen <= 0) 106 throw new IllegalArgumentException(); 107 int lines = (iLen + blockLen - 1) / blockLen; 108 int bufLen = ((iLen + 2) / 3) * 4 + lines * lineSeparator.length(); 109 StringBuilder buf = new StringBuilder(bufLen); 110 int ip = 0; 111 while (ip < iLen) { 112 int l = Math.min(iLen - ip, blockLen); 113 buf.append(encode(in, iOff + ip, l)); 114 buf.append(lineSeparator); 115 ip += l; 116 } 117 return buf.toString(); 118 } 119 120 /** 121 * Encodes a byte array into Base64 format. No blanks or line breaks are 122 * inserted in the output. 123 * 124 * @param in 125 * An array containing the data bytes to be encoded. 126 * @return A character array containing the Base64 encoded data. 127 */ encode(byte[] in)128 public static char[] encode(byte[] in) { 129 return encode(in, 0, in.length); 130 } 131 132 /** 133 * Encodes a byte array into Base64 format. No blanks or line breaks are 134 * inserted in the output. 135 * 136 * @param in 137 * An array containing the data bytes to be encoded. 138 * @param iLen 139 * Number of bytes to process in <code>in</code>. 140 * @return A character array containing the Base64 encoded data. 141 */ encode(byte[] in, int iLen)142 public static char[] encode(byte[] in, int iLen) { 143 return encode(in, 0, iLen); 144 } 145 146 /** 147 * Encodes a byte array into Base64 format. No blanks or line breaks are 148 * inserted in the output. 149 * 150 * @param in 151 * An array containing the data bytes to be encoded. 152 * @param iOff 153 * Offset of the first byte in <code>in</code> to be processed. 154 * @param iLen 155 * Number of bytes to process in <code>in</code>, starting at 156 * <code>iOff</code>. 157 * @return A character array containing the Base64 encoded data. 158 */ encode(byte[] in, int iOff, int iLen)159 public static char[] encode(byte[] in, int iOff, int iLen) { 160 int oDataLen = (iLen * 4 + 2) / 3; // output length without padding 161 int oLen = ((iLen + 2) / 3) * 4; // output length including padding 162 char[] out = new char[oLen]; 163 int ip = iOff; 164 int iEnd = iOff + iLen; 165 int op = 0; 166 while (ip < iEnd) { 167 int i0 = in[ip++] & 0xff; 168 int i1 = ip < iEnd ? in[ip++] & 0xff : 0; 169 int i2 = ip < iEnd ? in[ip++] & 0xff : 0; 170 int o0 = i0 >>> 2; 171 int o1 = ((i0 & 3) << 4) | (i1 >>> 4); 172 int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); 173 int o3 = i2 & 0x3F; 174 out[op++] = map1[o0]; 175 out[op++] = map1[o1]; 176 out[op] = op < oDataLen ? map1[o2] : '='; 177 op++; 178 out[op] = op < oDataLen ? map1[o3] : '='; 179 op++; 180 } 181 return out; 182 } 183 184 /** 185 * Decodes a string from Base64 format. No blanks or line breaks are allowed 186 * within the Base64 encoded input data. 187 * 188 * @param s 189 * A Base64 String to be decoded. 190 * @return A String containing the decoded data. 191 * @throws IllegalArgumentException 192 * If the input is not valid Base64 encoded data. 193 */ 194 public static String decodeString(String s) { 195 return new String(decode(s)); 196 } 197 198 /** 199 * Decodes a byte array from Base64 format and ignores line separators, tabs 200 * and blanks. CR, LF, Tab and Space characters are ignored in the input 201 * data. This method is compatible with 202 * <code>sun.misc.BASE64Decoder.decodeBuffer(String)</code>. 203 * 204 * @param s 205 * A Base64 String to be decoded. 206 * @return An array containing the decoded data bytes. 207 * @throws IllegalArgumentException 208 * If the input is not valid Base64 encoded data. 209 */ 210 public static byte[] decodeLines(String s) { 211 char[] buf = new char[s.length()]; 212 int p = 0; 213 for (int ip = 0; ip < s.length(); ip++) { 214 char c = s.charAt(ip); 215 if (c != ' ' && c != '\r' && c != '\n' && c != '\t') 216 buf[p++] = c; 217 } 218 return decode(buf, 0, p); 219 } 220 221 /** 222 * Decodes a byte array from Base64 format. No blanks or line breaks are 223 * allowed within the Base64 encoded input data. 224 * 225 * @param s 226 * A Base64 String to be decoded. 227 * @return An array containing the decoded data bytes. 228 * @throws IllegalArgumentException 229 * If the input is not valid Base64 encoded data. 230 */ 231 public static byte[] decode(String s) { 232 return decode(s.toCharArray()); 233 } 234 235 /** 236 * Decodes a byte array from Base64 format. No blanks or line breaks are 237 * allowed within the Base64 encoded input data. 238 * 239 * @param in 240 * A character array containing the Base64 encoded data. 241 * @return An array containing the decoded data bytes. 242 * @throws IllegalArgumentException 243 * If the input is not valid Base64 encoded data. 244 */ 245 public static byte[] decode(char[] in) { 246 return decode(in, 0, in.length); 247 } 248 249 /** 250 * Decodes a byte array from Base64 format. No blanks or line breaks are 251 * allowed within the Base64 encoded input data. 252 * 253 * @param in 254 * A character array containing the Base64 encoded data. 255 * @param iOff 256 * Offset of the first character in <code>in</code> to be 257 * processed. 258 * @param iLen 259 * Number of characters to process in <code>in</code>, starting 260 * at <code>iOff</code>. 261 * @return An array containing the decoded data bytes. 262 * @throws IllegalArgumentException 263 * If the input is not valid Base64 encoded data. 264 */ 265 public static byte[] decode(char[] in, int iOff, int iLen) { 266 if (iLen % 4 != 0) 267 throw new IllegalArgumentException( 268 "Length of Base64 encoded input string is not a multiple of 4."); 269 while (iLen > 0 && in[iOff + iLen - 1] == '=') 270 iLen--; 271 int oLen = (iLen * 3) / 4; 272 byte[] out = new byte[oLen]; 273 int ip = iOff; 274 int iEnd = iOff + iLen; 275 int op = 0; 276 while (ip < iEnd) { 277 int i0 = in[ip++]; 278 int i1 = in[ip++]; 279 int i2 = ip < iEnd ? in[ip++] : 'A'; 280 int i3 = ip < iEnd ? in[ip++] : 'A'; 281 if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) 282 throw new IllegalArgumentException("Illegal character in Base64 encoded data."); 283 int b0 = map2[i0]; 284 int b1 = map2[i1]; 285 int b2 = map2[i2]; 286 int b3 = map2[i3]; 287 if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) 288 throw new IllegalArgumentException("Illegal character in Base64 encoded data."); 289 int o0 = (b0 << 2) | (b1 >>> 4); 290 int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); 291 int o2 = ((b2 & 3) << 6) | b3; 292 out[op++] = (byte) o0; 293 if (op < oLen) 294 out[op++] = (byte) o1; 295 if (op < oLen) 296 out[op++] = (byte) o2; 297 } 298 return out; 299 } 300 301 // Dummy constructor. 302 private Base64Coder() { 303 } 304 305 } // end class Base64Coder 306