blob: 151adc4ecb536a169cfcbadced6695c9ef095b33 [file] [log] [blame]
Stuart McCullochbb014372012-06-07 21:57:32 +00001package aQute.lib.base64;
2
3import java.io.*;
4
5/*
6 * Base 64 converter.
7 *
8 * TODO Implement string to byte[]
9 */
10public class Base64 {
11 byte[] data;
12
13 static final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
14 static byte[] values = new byte[128];
15
16 static {
17 for (int i = 0; i < values.length; i++) {
18 values[i] = -1;
19 }
20 // Create reverse index
21 for (int i = 0; i < alphabet.length(); i++) {
22 char c = alphabet.charAt(i);
23 values[c] = (byte) i;
24 }
25 }
26
27 public Base64(byte data[]) {
28 this.data = data;
29 }
30
31
32
33 public final static byte[] decodeBase64(String string) {
34 ByteArrayOutputStream bout= new ByteArrayOutputStream(string.length()*2/3);
35 StringReader rdr = new StringReader(string.trim());
36 try {
37 decode(rdr,bout);
38 } catch (Exception e) {
39 // cannot happen
40 }
41 return bout.toByteArray();
42 }
43
44 public final static void decode(Reader rdr, OutputStream out) throws Exception {
45 int register = 0;
46 int i = 0;
47 int pads = 0;
48
49 byte test[] = new byte[3];
50 int c;
51 while ((c=rdr.read()) >= 0) {
52
53 if (c > 0x7F)
54 throw new IllegalArgumentException(
55 "Invalid base64 character in " + rdr
56 + ", character value > 128 ");
57
58 int v = 0;
59 if ( c == '=' ) {
60 pads++;
61 } else {
62 v = values[c];
63 if ( v < 0 )
64 throw new IllegalArgumentException(
65 "Invalid base64 character in " + rdr + ", " + c );
66 }
67 register <<= 6;
68 register |= v;
69 test[2] = (byte) (register & 0xFF);
70 test[1] = (byte) ((register >> 8) & 0xFF);
71 test[0] = (byte) ((register >> 16) & 0xFF);
72
73 i++;
74
75 if ((i % 4) == 0) {
76 flush(out, register, pads);
77 register = 0;
78 pads = 0;
79 }
80 }
81 }
82
83 static private void flush(OutputStream out, int register, int pads) throws IOException {
84 switch (pads) {
85 case 0:
86 out.write(0xFF & (register >> 16));
87 out.write(0xFF & (register >> 8));
88 out.write(0xFF & (register >> 0));
89 break;
90
91 case 1:
92 out.write(0xFF & (register >> 16));
93 out.write(0xFF & (register >> 8));
94 break;
95
96 case 2:
97 out.write(0xFF & (register >> 16));
98 }
99 }
100
101 public Base64(String s) {
102 data = decodeBase64(s);
103 }
104
105 public String toString() {
106 return encodeBase64(data);
107 }
108
109 public static String encodeBase64(byte data[]) {
110 StringWriter sw = new StringWriter();
111 ByteArrayInputStream bin = new ByteArrayInputStream(data);
112 try {
113 encode(bin,sw);
114 } catch (IOException e) {
115 // can't happen
116 }
117 return sw.toString();
118 }
119
120
121 public Object toData() {
122 return data;
123 }
124
125 public static void encode(InputStream in, Appendable sb) throws IOException {
126 //StringBuilder sb = new StringBuilder();
127 int buf = 0;
128 int bits = 0;
129 int out = 0;
130
131 while (true) {
132 if (bits >= 6) {
133 bits -= 6;
134 int v = 0x3F & (buf >> bits);
135 sb.append(alphabet.charAt(v));
136 out++;
137 } else {
138 int c = in.read();
139 if (c < 0)
140 break;
141
142 buf <<= 8;
143 buf |= 0xFF & c;
144 bits += 8;
145 }
146 }
147 if (bits != 0) {// must be less than 7
148 sb.append(alphabet.charAt(0x3F & (buf << (6 - bits))));
149 out++;
150 }
151 int mod = 4 - (out % 4);
152 if (mod != 4) {
153 for (int i = 0; i < mod; i++)
154 sb.append('=');
155 }
156 }
157
158}