Frames | No Frames |
1: /* Base64.java -- Base64 encoding and decoding. 2: Copyright (C) 2006 Free Software Foundation, Inc. 3: 4: This file is a part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2 of the License, or (at 9: your option) any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; if not, write to the Free Software 18: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 19: USA 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. 37: 38: -- 39: Base64 encoding derived from ISC's DHCP. Copyright notices from DHCP 40: follow. See http://www.isc.org/products/DHCP/. 41: 42: Copyright (c) 1996 by Internet Software Consortium. 43: 44: Permission to use, copy, modify, and distribute this software for any 45: purpose with or without fee is hereby granted, provided that the above 46: copyright notice and this permission notice appear in all copies. 47: 48: THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM 49: DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 50: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 51: INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 52: INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 53: FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 54: NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 55: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 56: 57: -- 58: Portions Copyright (c) 1995 by International Business Machines, Inc. 59: 60: International Business Machines, Inc. (hereinafter called IBM) grants 61: permission under its copyrights to use, copy, modify, and distribute 62: this Software with or without fee, provided that the above copyright 63: notice and all paragraphs of this notice appear in all copies, and 64: that the name of IBM not be used in connection with the marketing of 65: any product incorporating the Software or modifications thereof, 66: without specific, written prior permission. 67: 68: To the extent it has a right to do so, IBM grants an immunity from 69: suit under its patents, if any, for the use, sale or manufacture of 70: products to the extent that such products are used for performing 71: Domain Name System dynamic updates in TCP/IP networks by means of the 72: Software. No immunity is granted for any product per se or for any 73: other function of any product. 74: 75: THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, 76: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 77: PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, 78: DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 79: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 80: SOFTWARE, EVEN IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH 81: DAMAGES. */ 82: 83: 84: package gnu.javax.net.ssl; 85: 86: import java.io.ByteArrayOutputStream; 87: import java.io.IOException; 88: 89: public final class Base64 90: { 91: 92: // No constructor. 93: private Base64() { } 94: 95: // Class methods. 96: // ------------------------------------------------------------------------- 97: 98: /** Base-64 characters. */ 99: private static final String BASE_64 = 100: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 101: 102: /** Base-64 padding character. */ 103: private static final char BASE_64_PAD = '='; 104: 105: /** 106: * Base64 encode a byte array, returning the returning string. 107: * 108: * @param buf The byte array to encode. 109: * @param tw The total length of any line, 0 for unlimited. 110: * @return <tt>buf</tt> encoded in Base64. 111: */ 112: public static String encode(byte[] buf, int tw) 113: { 114: int srcLength = buf.length; 115: byte[] input = new byte[3]; 116: int[] output = new int[4]; 117: StringBuffer out = new StringBuffer(); 118: int i = 0; 119: int chars = 0; 120: 121: while (srcLength > 2) 122: { 123: input[0] = buf[i++]; 124: input[1] = buf[i++]; 125: input[2] = buf[i++]; 126: srcLength -= 3; 127: 128: output[0] = (input[0] & 0xff) >>> 2; 129: output[1] = ((input[0] & 0x03) << 4) + ((input[1] & 0xff) >>> 4); 130: output[2] = ((input[1] & 0x0f) << 2) + ((input[2] & 0xff) >>> 6); 131: output[3] = input[2] & 0x3f; 132: 133: out.append(BASE_64.charAt(output[0])); 134: if (tw > 0 && ++chars % tw == 0) 135: { 136: out.append("\n"); 137: } 138: out.append(BASE_64.charAt(output[1])); 139: if (tw > 0 && ++chars % tw == 0) 140: { 141: out.append("\n"); 142: } 143: out.append(BASE_64.charAt(output[2])); 144: if (tw > 0 && ++chars % tw == 0) 145: { 146: out.append("\n"); 147: } 148: out.append(BASE_64.charAt(output[3])); 149: if (tw > 0 && ++chars % tw == 0) 150: { 151: out.append("\n"); 152: } 153: } 154: 155: if (srcLength != 0) 156: { 157: input[0] = input[1] = input[2] = 0; 158: for (int j = 0; j < srcLength; j++) 159: { 160: input[j] = buf[i+j]; 161: } 162: output[0] = (input[0] & 0xff) >>> 2; 163: output[1] = ((input[0] & 0x03) << 4) + ((input[1] & 0xff) >>> 4); 164: output[2] = ((input[1] & 0x0f) << 2) + ((input[2] & 0xff) >>> 6); 165: 166: out.append(BASE_64.charAt(output[0])); 167: if (tw > 0 && ++chars % tw == 0) 168: { 169: out.append("\n"); 170: } 171: out.append(BASE_64.charAt(output[1])); 172: if (tw > 0 && ++chars % tw == 0) 173: { 174: out.append("\n"); 175: } 176: if (srcLength == 1) 177: { 178: out.append(BASE_64_PAD); 179: } 180: else 181: { 182: out.append(BASE_64.charAt(output[2])); 183: } 184: if (tw > 0 && ++chars % tw == 0) 185: { 186: out.append("\n"); 187: } 188: out.append(BASE_64_PAD); 189: if (tw > 0 && ++chars % tw == 0) 190: { 191: out.append("\n"); 192: } 193: } 194: if (tw > 0) 195: { 196: out.append("\n"); 197: } 198: 199: return out.toString(); 200: } 201: 202: /** 203: * Decode a Base-64 string into a byte array. 204: * 205: * @param b64 The Base-64 encoded string. 206: * @return The decoded bytes. 207: * @throws java.io.IOException If the argument is not a valid Base-64 208: * encoding. 209: */ 210: public static byte[] decode(String b64) throws IOException 211: { 212: ByteArrayOutputStream result = new ByteArrayOutputStream(b64.length() / 3); 213: int state = 0, i; 214: byte temp = 0; 215: 216: for (i = 0; i < b64.length(); i++) 217: { 218: if (Character.isWhitespace(b64.charAt(i))) 219: { 220: continue; 221: } 222: if (b64.charAt(i) == BASE_64_PAD) 223: { 224: break; 225: } 226: 227: int pos = BASE_64.indexOf(b64.charAt(i)); 228: if (pos < 0) 229: { 230: throw new IOException("non-Base64 character " + b64.charAt(i)); 231: } 232: switch (state) 233: { 234: case 0: 235: temp = (byte) (pos - BASE_64.indexOf('A') << 2); 236: state = 1; 237: break; 238: 239: case 1: 240: temp |= (byte) (pos - BASE_64.indexOf('A') >>> 4); 241: result.write(temp); 242: temp = (byte) ((pos - BASE_64.indexOf('A') & 0x0f) << 4); 243: state = 2; 244: break; 245: 246: case 2: 247: temp |= (byte) ((pos - BASE_64.indexOf('A') & 0x7f) >>> 2); 248: result.write(temp); 249: temp = (byte) ((pos - BASE_64.indexOf('A') & 0x03) << 6); 250: state = 3; 251: break; 252: 253: case 3: 254: temp |= (byte) (pos - BASE_64.indexOf('A') & 0xff); 255: result.write(temp); 256: state = 0; 257: break; 258: 259: default: 260: throw new Error("this statement should be unreachable"); 261: } 262: } 263: 264: if (i < b64.length() && b64.charAt(i) == BASE_64_PAD) 265: { 266: switch (state) 267: { 268: case 0: 269: case 1: 270: throw new IOException("malformed Base64 sequence"); 271: 272: case 2: 273: for ( ; i < b64.length(); i++) 274: { 275: if (!Character.isWhitespace(b64.charAt(i))) 276: { 277: break; 278: } 279: } 280: // We must see a second pad character here. 281: if (b64.charAt(i) != BASE_64_PAD) 282: { 283: throw new IOException("malformed Base64 sequence"); 284: } 285: i++; 286: // Fall-through. 287: 288: case 3: 289: i++; 290: for ( ; i < b64.length(); i++) 291: { 292: // We should only see whitespace after this. 293: if (!Character.isWhitespace(b64.charAt(i))) 294: { 295: System.err.println(b64.charAt(i)); 296: throw new IOException("malformed Base64 sequence"); 297: } 298: } 299: } 300: } 301: else 302: { 303: if (state != 0) 304: { 305: throw new IOException("malformed Base64 sequence"); 306: } 307: } 308: 309: return result.toByteArray(); 310: } 311: }