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