001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.security;
023:
024: /** Base64 encoding/decoding utilities
025: *
026: * @author Scott.Stark@jboss.org
027: * @version $Revison:$
028: */
029: public class Base64Utils {
030: private static final char[] base64Table = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"
031: .toCharArray();
032: public static final String BASE64_ENCODING = "BASE64";
033: public static final String BASE16_ENCODING = "HEX";
034:
035: // These functions assume that the byte array has MSB at 0, LSB at end.
036: // Reverse the byte array (not the String) if this is not the case.
037: // All base64 strings are in natural order, least significant digit last.
038: public static String tob64(byte[] buffer) {
039: boolean notleading = false;
040: int len = buffer.length, pos = len % 3, c;
041: byte b0 = 0, b1 = 0, b2 = 0;
042: StringBuffer sb = new StringBuffer();
043:
044: switch (pos) {
045: case 1:
046: b2 = buffer[0];
047: break;
048: case 2:
049: b1 = buffer[0];
050: b2 = buffer[1];
051: break;
052: }
053: do {
054: c = (b0 & 0xfc) >>> 2;
055: if (notleading || c != 0) {
056: sb.append(base64Table[c]);
057: notleading = true;
058: }
059: c = ((b0 & 3) << 4) | ((b1 & 0xf0) >>> 4);
060: if (notleading || c != 0) {
061: sb.append(base64Table[c]);
062: notleading = true;
063: }
064: c = ((b1 & 0xf) << 2) | ((b2 & 0xc0) >>> 6);
065: if (notleading || c != 0) {
066: sb.append(base64Table[c]);
067: notleading = true;
068: }
069: c = b2 & 0x3f;
070: if (notleading || c != 0) {
071: sb.append(base64Table[c]);
072: notleading = true;
073: }
074: if (pos >= len)
075: break;
076: else {
077: try {
078: b0 = buffer[pos++];
079: b1 = buffer[pos++];
080: b2 = buffer[pos++];
081: } catch (ArrayIndexOutOfBoundsException e) {
082: break;
083: }
084: }
085: } while (true);
086:
087: if (notleading)
088: return sb.toString();
089: else
090: return "0";
091: }
092:
093: public static byte[] fromb64(String str)
094: throws NumberFormatException {
095: int len = str.length();
096: if (len == 0)
097: throw new NumberFormatException("Empty Base64 string");
098:
099: byte[] a = new byte[len + 1];
100: char c;
101: int i, j;
102:
103: for (i = 0; i < len; ++i) {
104: c = str.charAt(i);
105: try {
106: for (j = 0; c != base64Table[j]; ++j)
107: ;
108: } catch (Exception e) {
109: throw new NumberFormatException(
110: "Illegal Base64 character");
111: }
112: a[i] = (byte) j;
113: }
114:
115: i = len - 1;
116: j = len;
117: try {
118: while (true) {
119: a[j] = a[i];
120: if (--i < 0)
121: break;
122: a[j] |= (a[i] & 3) << 6;
123: --j;
124: a[j] = (byte) ((a[i] & 0x3c) >>> 2);
125: if (--i < 0)
126: break;
127: a[j] |= (a[i] & 0xf) << 4;
128: --j;
129: a[j] = (byte) ((a[i] & 0x30) >>> 4);
130: if (--i < 0)
131: break;
132: a[j] |= (a[i] << 2);
133:
134: // Nasty, evil bug in Microsloth's Java interpreter under
135: // Netscape: The following three lines of code are supposed
136: // to be equivalent, but under the Windows NT VM (Netscape3.0)
137: // using either of the two commented statements would cause
138: // the zero to be placed in a[j] *before* decrementing j.
139: // Weeeeird.
140: a[j - 1] = 0;
141: --j;
142: // a[--j] = 0;
143: // --j; a[j] = 0;
144:
145: if (--i < 0)
146: break;
147: }
148: } catch (Exception e) {
149:
150: }
151:
152: try {
153: while (a[j] == 0)
154: ++j;
155: } catch (Exception e) {
156: return new byte[1];
157: }
158:
159: byte[] result = new byte[len - j + 1];
160: System.arraycopy(a, j, result, 0, len - j + 1);
161: return result;
162: }
163:
164: }
|