001: // Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
002:
003: package org.xbill.DNS.utils;
004:
005: import java.io.*;
006:
007: /**
008: * Routines for converting between Strings of base64-encoded data and arrays of
009: * binary data.
010: *
011: * @author Brian Wellington
012: */
013:
014: public class base64 {
015:
016: private static final String Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
017:
018: private base64() {
019: }
020:
021: /**
022: * Convert binary data to a base64-encoded String
023: * @param b An array containing binary data
024: * @return A String containing the encoded data
025: */
026: public static String toString(byte[] b) {
027: ByteArrayOutputStream os = new ByteArrayOutputStream();
028:
029: for (int i = 0; i < (b.length + 2) / 3; i++) {
030: short[] s = new short[3];
031: short[] t = new short[4];
032: for (int j = 0; j < 3; j++) {
033: if ((i * 3 + j) < b.length)
034: s[j] = (short) (b[i * 3 + j] & 0xFF);
035: else
036: s[j] = -1;
037: }
038:
039: t[0] = (short) (s[0] >> 2);
040: if (s[1] == -1)
041: t[1] = (short) (((s[0] & 0x3) << 4));
042: else
043: t[1] = (short) (((s[0] & 0x3) << 4) + (s[1] >> 4));
044: if (s[1] == -1)
045: t[2] = t[3] = 64;
046: else if (s[2] == -1) {
047: t[2] = (short) (((s[1] & 0xF) << 2));
048: t[3] = 64;
049: } else {
050: t[2] = (short) (((s[1] & 0xF) << 2) + (s[2] >> 6));
051: t[3] = (short) (s[2] & 0x3F);
052: }
053: for (int j = 0; j < 4; j++)
054: os.write(Base64.charAt(t[j]));
055: }
056: return new String(os.toByteArray());
057: }
058:
059: /**
060: * Formats data into a nicely formatted base64 encoded String
061: * @param b An array containing binary data
062: * @param lineLength The number of characters per line
063: * @param prefix A string prefixing the characters on each line
064: * @param addClose Whether to add a close parenthesis or not
065: * @return A String representing the formatted output
066: */
067: public static String formatString(byte[] b, int lineLength,
068: String prefix, boolean addClose) {
069: String s = toString(b);
070: StringBuffer sb = new StringBuffer();
071: for (int i = 0; i < s.length(); i += lineLength) {
072: sb.append(prefix);
073: if (i + lineLength >= s.length()) {
074: sb.append(s.substring(i));
075: if (addClose)
076: sb.append(" )");
077: } else {
078: sb.append(s.substring(i, i + lineLength));
079: sb.append("\n");
080: }
081: }
082: return sb.toString();
083: }
084:
085: /**
086: * Convert a base64-encoded String to binary data
087: * @param str A String containing the encoded data
088: * @return An array containing the binary data, or null if the string is invalid
089: */
090: public static byte[] fromString(String str) {
091: ByteArrayOutputStream bs = new ByteArrayOutputStream();
092: byte[] raw = str.getBytes();
093: for (int i = 0; i < raw.length; i++) {
094: if (!Character.isWhitespace((char) raw[i]))
095: bs.write(raw[i]);
096: }
097: byte[] in = bs.toByteArray();
098: if (in.length % 4 != 0) {
099: return null;
100: }
101:
102: bs.reset();
103: DataOutputStream ds = new DataOutputStream(bs);
104:
105: for (int i = 0; i < (in.length + 3) / 4; i++) {
106: short[] s = new short[4];
107: short[] t = new short[3];
108:
109: for (int j = 0; j < 4; j++)
110: s[j] = (short) Base64.indexOf(in[i * 4 + j]);
111:
112: t[0] = (short) ((s[0] << 2) + (s[1] >> 4));
113: if (s[2] == 64) {
114: t[1] = t[2] = (short) (-1);
115: if ((s[1] & 0xF) != 0)
116: return null;
117: } else if (s[3] == 64) {
118: t[1] = (short) (((s[1] << 4) + (s[2] >> 2)) & 0xFF);
119: t[2] = (short) (-1);
120: if ((s[2] & 0x3) != 0)
121: return null;
122: } else {
123: t[1] = (short) (((s[1] << 4) + (s[2] >> 2)) & 0xFF);
124: t[2] = (short) (((s[2] << 6) + s[3]) & 0xFF);
125: }
126:
127: try {
128: for (int j = 0; j < 3; j++)
129: if (t[j] >= 0)
130: ds.writeByte(t[j]);
131: } catch (IOException e) {
132: }
133: }
134: return bs.toByteArray();
135: }
136:
137: }
|