blob: 33f0a8a801d5b2c451f9527f24445b9308202227 [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
Stuart McCullochbb014372012-06-07 21:57:32 +000031 public final static byte[] decodeBase64(String string) {
Stuart McCulloch2286f232012-06-15 13:27:53 +000032 ByteArrayOutputStream bout = new ByteArrayOutputStream(string.length() * 2 / 3);
Stuart McCullochbb014372012-06-07 21:57:32 +000033 StringReader rdr = new StringReader(string.trim());
34 try {
Stuart McCulloch2286f232012-06-15 13:27:53 +000035 decode(rdr, bout);
36 }
37 catch (Exception e) {
Stuart McCullochbb014372012-06-07 21:57:32 +000038 // cannot happen
39 }
40 return bout.toByteArray();
41 }
Stuart McCulloch2286f232012-06-15 13:27:53 +000042
Stuart McCullochbb014372012-06-07 21:57:32 +000043 public final static void decode(Reader rdr, OutputStream out) throws Exception {
44 int register = 0;
45 int i = 0;
46 int pads = 0;
47
48 byte test[] = new byte[3];
49 int c;
Stuart McCulloch2286f232012-06-15 13:27:53 +000050 while ((c = rdr.read()) >= 0) {
Stuart McCullochbb014372012-06-07 21:57:32 +000051
52 if (c > 0x7F)
Stuart McCulloch2286f232012-06-15 13:27:53 +000053 throw new IllegalArgumentException("Invalid base64 character in " + rdr + ", character value > 128 ");
54
Stuart McCullochbb014372012-06-07 21:57:32 +000055 int v = 0;
Stuart McCulloch2286f232012-06-15 13:27:53 +000056 if (c == '=') {
Stuart McCullochbb014372012-06-07 21:57:32 +000057 pads++;
58 } else {
59 v = values[c];
Stuart McCulloch2286f232012-06-15 13:27:53 +000060 if (v < 0)
61 throw new IllegalArgumentException("Invalid base64 character in " + rdr + ", " + c);
62 }
Stuart McCullochbb014372012-06-07 21:57:32 +000063 register <<= 6;
64 register |= v;
65 test[2] = (byte) (register & 0xFF);
66 test[1] = (byte) ((register >> 8) & 0xFF);
67 test[0] = (byte) ((register >> 16) & 0xFF);
68
69 i++;
70
71 if ((i % 4) == 0) {
72 flush(out, register, pads);
73 register = 0;
74 pads = 0;
75 }
76 }
77 }
78
79 static private void flush(OutputStream out, int register, int pads) throws IOException {
80 switch (pads) {
Stuart McCulloch2286f232012-06-15 13:27:53 +000081 case 0 :
82 out.write(0xFF & (register >> 16));
83 out.write(0xFF & (register >> 8));
84 out.write(0xFF & (register >> 0));
85 break;
86
87 case 1 :
88 out.write(0xFF & (register >> 16));
89 out.write(0xFF & (register >> 8));
90 break;
91
92 case 2 :
93 out.write(0xFF & (register >> 16));
Stuart McCullochbb014372012-06-07 21:57:32 +000094 }
95 }
96
97 public Base64(String s) {
98 data = decodeBase64(s);
99 }
100
Stuart McCulloch55d4dfe2012-08-07 10:57:21 +0000101 @Override
Stuart McCullochbb014372012-06-07 21:57:32 +0000102 public String toString() {
103 return encodeBase64(data);
104 }
105
106 public static String encodeBase64(byte data[]) {
107 StringWriter sw = new StringWriter();
108 ByteArrayInputStream bin = new ByteArrayInputStream(data);
109 try {
Stuart McCulloch2286f232012-06-15 13:27:53 +0000110 encode(bin, sw);
111 }
112 catch (IOException e) {
Stuart McCullochbb014372012-06-07 21:57:32 +0000113 // can't happen
114 }
115 return sw.toString();
116 }
Stuart McCullochbb014372012-06-07 21:57:32 +0000117
118 public Object toData() {
119 return data;
120 }
121
122 public static void encode(InputStream in, Appendable sb) throws IOException {
Stuart McCulloch2286f232012-06-15 13:27:53 +0000123 // StringBuilder sb = new StringBuilder();
Stuart McCullochbb014372012-06-07 21:57:32 +0000124 int buf = 0;
125 int bits = 0;
126 int out = 0;
Stuart McCulloch2286f232012-06-15 13:27:53 +0000127
Stuart McCullochbb014372012-06-07 21:57:32 +0000128 while (true) {
129 if (bits >= 6) {
130 bits -= 6;
131 int v = 0x3F & (buf >> bits);
132 sb.append(alphabet.charAt(v));
133 out++;
134 } else {
135 int c = in.read();
136 if (c < 0)
137 break;
138
139 buf <<= 8;
140 buf |= 0xFF & c;
141 bits += 8;
142 }
143 }
144 if (bits != 0) {// must be less than 7
145 sb.append(alphabet.charAt(0x3F & (buf << (6 - bits))));
146 out++;
147 }
148 int mod = 4 - (out % 4);
149 if (mod != 4) {
150 for (int i = 0; i < mod; i++)
151 sb.append('=');
152 }
153 }
154
155}