001: /***** BEGIN LICENSE BLOCK *****
002: * Version: CPL 1.0/GPL 2.0/LGPL 2.1
003: *
004: * The contents of this file are subject to the Common Public
005: * License Version 1.0 (the "License"); you may not use this file
006: * except in compliance with the License. You may obtain a copy of
007: * the License at http://www.eclipse.org/legal/cpl-v10.html
008: *
009: * Software distributed under the License is distributed on an "AS
010: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
011: * implied. See the License for the specific language governing
012: * rights and limitations under the License.
013: *
014: * Copyright (C) 2007 Ola Bini <ola@ologix.com>
015: *
016: * Alternatively, the contents of this file may be used under the terms of
017: * either of the GNU General Public License Version 2 or later (the "GPL"),
018: * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
019: * in which case the provisions of the GPL or the LGPL are applicable instead
020: * of those above. If you wish to allow use of your version of this file only
021: * under the terms of either the GPL or the LGPL, and not to allow others to
022: * use your version of this file under the terms of the CPL, indicate your
023: * decision by deleting the provisions above and replace them with the notice
024: * and other provisions required by the GPL or the LGPL. If you do not delete
025: * the provisions above, a recipient may use your version of this file under
026: * the terms of any one of the CPL, the GPL or the LGPL.
027: ***** END LICENSE BLOCK *****/package org.jvyamlb.util;
028:
029: /**
030: * @author <a href="mailto:ola.bini@ki.se">Ola Bini</a>
031: */
032: public class Base64Coder {
033: // Mapping table from 6-bit nibbles to Base64 characters.
034: private final static char[] map1 = new char[64];
035: static {
036: int i = 0;
037: for (char c = 'A'; c <= 'Z'; c++)
038: map1[i++] = c;
039: for (char c = 'a'; c <= 'z'; c++)
040: map1[i++] = c;
041: for (char c = '0'; c <= '9'; c++)
042: map1[i++] = c;
043: map1[i++] = '+';
044: map1[i++] = '/';
045: }
046:
047: // Mapping table from Base64 characters to 6-bit nibbles.
048: private final static byte[] map2 = new byte[128];
049: static {
050: for (int i = 0; i < map2.length; i++)
051: map2[i] = -1;
052: for (int i = 0; i < 64; i++)
053: map2[map1[i]] = (byte) i;
054: }
055:
056: /**
057: * Encodes a string into Base64 format.
058: * No blanks or line breaks are inserted.
059: * @param s a String to be encoded.
060: * @return A String with the Base64 encoded data.
061: */
062: public static String encode(final String s) {
063: return new String(encode(s.getBytes()));
064: }
065:
066: /**
067: * Encodes a byte array into Base64 format.
068: * No blanks or line breaks are inserted.
069: * @param in an array containing the data bytes to be encoded.
070: * @return A character array with the Base64 encoded data.
071: */
072: public static char[] encode(final byte[] in) {
073: int iLen = in.length;
074: int oDataLen = (iLen * 4 + 2) / 3; // output length without padding
075: int oLen = ((iLen + 2) / 3) * 4; // output length including padding
076: char[] out = new char[oLen];
077: int ip = 0;
078: int op = 0;
079: while (ip < iLen) {
080: int i0 = in[ip++] & 0xff;
081: int i1 = ip < iLen ? in[ip++] & 0xff : 0;
082: int i2 = ip < iLen ? in[ip++] & 0xff : 0;
083: int o0 = i0 >>> 2;
084: int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
085: int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
086: int o3 = i2 & 0x3F;
087: out[op++] = map1[o0];
088: out[op++] = map1[o1];
089: out[op] = op < oDataLen ? map1[o2] : '=';
090: op++;
091: out[op] = op < oDataLen ? map1[o3] : '=';
092: op++;
093: }
094: return out;
095: }
096:
097: /**
098: * Decodes Base64 data.
099: * No blanks or line breaks are allowed within the Base64 encoded data.
100: * @param in a character array containing the Base64 encoded data.
101: * @return An array containing the decoded data bytes.
102: * @throws IllegalArgumentException if the input is not valid Base64 encoded data.
103: */
104: public static byte[] decode(final byte[] in) {
105: int iLen = in.length;
106: if (iLen % 4 != 0)
107: throw new IllegalArgumentException(
108: "Length of Base64 encoded input string is not a multiple of 4.");
109: while (iLen > 0 && in[iLen - 1] == '=')
110: iLen--;
111: int oLen = (iLen * 3) / 4;
112: byte[] out = new byte[oLen];
113: int ip = 0;
114: int op = 0;
115: while (ip < iLen) {
116: int i0 = in[ip++];
117: int i1 = in[ip++];
118: int i2 = ip < iLen ? in[ip++] : 'A';
119: int i3 = ip < iLen ? in[ip++] : 'A';
120: if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
121: throw new IllegalArgumentException(
122: "Illegal character in Base64 encoded data.");
123: int b0 = map2[i0];
124: int b1 = map2[i1];
125: int b2 = map2[i2];
126: int b3 = map2[i3];
127: if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
128: throw new IllegalArgumentException(
129: "Illegal character in Base64 encoded data.");
130: int o0 = (b0 << 2) | (b1 >>> 4);
131: int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
132: int o2 = ((b2 & 3) << 6) | b3;
133: out[op++] = (byte) o0;
134: if (op < oLen)
135: out[op++] = (byte) o1;
136: if (op < oLen)
137: out[op++] = (byte) o2;
138: }
139: return out;
140: }
141: }
|