1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.jetty.security;
16
17 import java.io.UnsupportedEncodingException;
18
19 import org.mortbay.util.StringUtil;
20
21
22
23
24
25
26
27
28
29
30
31
32 public class B64Code
33 {
34
35 static final char pad='=';
36 static final char[] nibble2code=
37 {
38 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
39 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
40 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
41 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
42 };
43
44 static byte[] code2nibble=null;
45
46 static
47 {
48 code2nibble=new byte[256];
49 for (int i=0;i<256;i++)
50 code2nibble[i]=-1;
51 for (byte b=0;b<64;b++)
52 code2nibble[(byte)nibble2code[b]]=b;
53 code2nibble[(byte)pad]=0;
54 }
55
56
57
58
59
60
61
62
63 static public String encode(String s)
64 {
65 try
66 {
67 return encode(s,null);
68 }
69 catch (UnsupportedEncodingException e)
70 {
71 throw new IllegalArgumentException(e.toString());
72 }
73 }
74
75
76
77
78
79
80
81
82
83
84 static public String encode(String s,String charEncoding)
85 throws UnsupportedEncodingException
86 {
87 byte[] bytes;
88 if (charEncoding==null)
89 bytes=s.getBytes(StringUtil.__ISO_8859_1);
90 else
91 bytes=s.getBytes(charEncoding);
92
93 return new String(encode(bytes));
94 }
95
96
97
98
99
100
101
102
103
104 static public char[] encode(byte[] b)
105 {
106 if (b==null)
107 return null;
108
109 int bLen=b.length;
110 char r[]=new char[((bLen+2)/3)*4];
111 int ri=0;
112 int bi=0;
113 byte b0, b1, b2;
114 int stop=(bLen/3)*3;
115 while (bi<stop)
116 {
117 b0=b[bi++];
118 b1=b[bi++];
119 b2=b[bi++];
120 r[ri++]=nibble2code[(b0>>>2)&0x3f];
121 r[ri++]=nibble2code[(b0<<4)&0x3f|(b1>>>4)&0x0f];
122 r[ri++]=nibble2code[(b1<<2)&0x3f|(b2>>>6)&0x03];
123 r[ri++]=nibble2code[b2&077];
124 }
125
126 if (bLen!=bi)
127 {
128 switch (bLen%3)
129 {
130 case 2:
131 b0=b[bi++];
132 b1=b[bi++];
133 r[ri++]=nibble2code[(b0>>>2)&0x3f];
134 r[ri++]=nibble2code[(b0<<4)&0x3f|(b1>>>4)&0x0f];
135 r[ri++]=nibble2code[(b1<<2)&0x3f];
136 r[ri++]=pad;
137 break;
138
139 case 1:
140 b0=b[bi++];
141 r[ri++]=nibble2code[(b0>>>2)&0x3f];
142 r[ri++]=nibble2code[(b0<<4)&0x3f];
143 r[ri++]=pad;
144 r[ri++]=pad;
145 break;
146
147 default:
148 break;
149 }
150 }
151
152 return r;
153 }
154
155
156
157
158
159
160
161
162
163 static public String decode(String s)
164 {
165 try
166 {
167 return decode(s,StringUtil.__ISO_8859_1);
168 }
169 catch (UnsupportedEncodingException e)
170 {
171 throw new IllegalArgumentException(e.toString());
172 }
173 }
174
175
176
177
178
179
180
181
182
183
184
185 static public String decode(String s,String charEncoding)
186 throws UnsupportedEncodingException
187 {
188 byte[] decoded=decode(s.toCharArray());
189
190 if (charEncoding==null)
191 return new String(decoded);
192 return new String(decoded,charEncoding);
193 }
194
195
196
197
198
199
200
201
202
203
204
205
206
207 static public byte[] decode(char[] b)
208 {
209 if (b==null)
210 return null;
211
212 int bLen=b.length;
213 if (bLen%4!=0)
214 throw new IllegalArgumentException("Input block size is not 4");
215
216 int li=bLen-1;
217 while (li>=0 && b[li]==(byte)pad)
218 li--;
219
220 if (li<0)
221 return new byte[0];
222
223
224 int rLen=((li+1)*3)/4;
225 byte r[]=new byte[rLen];
226 int ri=0;
227 int bi=0;
228 int stop=(rLen/3)*3;
229 byte b0,b1,b2,b3;
230 try
231 {
232 while (ri<stop)
233 {
234 b0=code2nibble[b[bi++]];
235 b1=code2nibble[b[bi++]];
236 b2=code2nibble[b[bi++]];
237 b3=code2nibble[b[bi++]];
238 if (b0<0 || b1<0 || b2<0 || b3<0)
239 throw new IllegalArgumentException("Not B64 encoded");
240
241 r[ri++]=(byte)(b0<<2|b1>>>4);
242 r[ri++]=(byte)(b1<<4|b2>>>2);
243 r[ri++]=(byte)(b2<<6|b3);
244 }
245
246 if (rLen!=ri)
247 {
248 switch (rLen%3)
249 {
250 case 2:
251 b0=code2nibble[b[bi++]];
252 b1=code2nibble[b[bi++]];
253 b2=code2nibble[b[bi++]];
254 if (b0<0 || b1<0 || b2<0)
255 throw new IllegalArgumentException("Not B64 encoded");
256 r[ri++]=(byte)(b0<<2|b1>>>4);
257 r[ri++]=(byte)(b1<<4|b2>>>2);
258 break;
259
260 case 1:
261 b0=code2nibble[b[bi++]];
262 b1=code2nibble[b[bi++]];
263 if (b0<0 || b1<0)
264 throw new IllegalArgumentException("Not B64 encoded");
265 r[ri++]=(byte)(b0<<2|b1>>>4);
266 break;
267
268 default:
269 break;
270 }
271 }
272 }
273 catch (IndexOutOfBoundsException e)
274 {
275 throw new IllegalArgumentException("char "+bi
276 +" was not B64 encoded");
277 }
278
279 return r;
280 }
281 }