KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > w3c > tools > codec > Base64Decoder


1 /*
2  * Copyright © World Wide Web Consortium, (Massachusetts Institute of Technology,
3  * Institut National de Recherche en Informatique et en Automatique, Keio University).
4  * All Rights Reserved. http://www.w3.org/Consortium/Legal/
5  */

6 package org.w3c.tools.codec;
7
8 import java.io.ByteArrayInputStream JavaDoc;
9 import java.io.ByteArrayOutputStream JavaDoc;
10 import java.io.FileInputStream JavaDoc;
11 import java.io.IOException JavaDoc;
12 import java.io.InputStream JavaDoc;
13 import java.io.OutputStream JavaDoc;
14 import java.io.UnsupportedEncodingException JavaDoc;
15
16 /**
17  * Decode a BASE64 encoded input stream to some output stream.
18  * This class implements BASE64 decoding, as specified in the
19  * <a HREF="http://ds.internic.net/rfc/rfc1521.txt">MIME specification</a>.
20  * @see org.w3c.tools.codec.Base64Encoder
21  */

22 public class Base64Decoder
23 {
24     private static final int BUFFER_SIZE = 1024;
25
26     InputStream JavaDoc in = null;
27     OutputStream JavaDoc out = null;
28     boolean stringp = false;
29
30     private void printHex(int x)
31     {
32         int h = (x & 0xf0) >> 4;
33         int l = (x & 0x0f);
34         System.out.print(
35             (new Character JavaDoc((char) ((h > 9) ? 'A' + h - 10 : '0' + h)))
36                 .toString()
37                 + (new Character JavaDoc((char) ((l > 9) ? 'A' + l - 10 : '0' + l)))
38                     .toString());
39     }
40
41     private void printHex(byte buf[], int off, int len)
42     {
43         while (off < len)
44         {
45             printHex(buf[off++]);
46             System.out.print(" ");
47         }
48         System.out.println("");
49     }
50
51     private void printHex(String JavaDoc s)
52     {
53         byte bytes[];
54         try
55         {
56             bytes = s.getBytes("ISO-8859-1");
57         }
58         catch (UnsupportedEncodingException JavaDoc ex)
59         {
60             throw new RuntimeException JavaDoc(
61                 this.getClass().getName()
62                     + "[printHex] Unable to convert"
63                     + "properly char to bytes");
64         }
65         printHex(bytes, 0, bytes.length);
66     }
67
68     private final int get1(byte buf[], int off)
69     {
70         return ((buf[off] & 0x3f) << 2) | ((buf[off + 1] & 0x30) >>> 4);
71     }
72
73     private final int get2(byte buf[], int off)
74     {
75         return ((buf[off + 1] & 0x0f) << 4) | ((buf[off + 2] & 0x3c) >>> 2);
76     }
77
78     private final int get3(byte buf[], int off)
79     {
80         return ((buf[off + 2] & 0x03) << 6) | (buf[off + 3] & 0x3f);
81     }
82
83     private final int check(int ch)
84     {
85         if ((ch >= 'A') && (ch <= 'Z'))
86         {
87             return ch - 'A';
88         }
89         else if ((ch >= 'a') && (ch <= 'z'))
90         {
91             return ch - 'a' + 26;
92         }
93         else if ((ch >= '0') && (ch <= '9'))
94         {
95             return ch - '0' + 52;
96         }
97         else
98         {
99             switch (ch)
100             {
101                 case '=' :
102                     return 65;
103                 case '+' :
104                     return 62;
105                 case '/' :
106                     return 63;
107                 default :
108                     return -1;
109             }
110         }
111     }
112
113     /**
114      * Do the actual decoding.
115      * Process the input stream by decoding it and emiting the resulting bytes
116      * into the output stream.
117      * @exception IOException If the input or output stream accesses failed.
118      * @exception Base64FormatException If the input stream is not compliant
119      * with the BASE64 specification.
120      */

121     public void process() throws IOException JavaDoc, Base64FormatException
122     {
123         byte buffer[] = new byte[BUFFER_SIZE];
124         byte chunk[] = new byte[4];
125         int got = -1;
126         int ready = 0;
127
128         fill : while ((got = in.read(buffer)) > 0)
129         {
130             int skiped = 0;
131             while (skiped < got)
132             {
133                 // Check for un-understood characters:
134
while (ready < 4)
135                 {
136                     if (skiped >= got)
137                         continue fill;
138                     int ch = check(buffer[skiped++]);
139                     if (ch >= 0)
140                         chunk[ready++] = (byte) ch;
141                 }
142                 if (chunk[2] == 65)
143                 {
144                     out.write(get1(chunk, 0));
145                     return;
146                 }
147                 else if (chunk[3] == 65)
148                 {
149                     out.write(get1(chunk, 0));
150                     out.write(get2(chunk, 0));
151                     return;
152                 }
153                 else
154                 {
155                     out.write(get1(chunk, 0));
156                     out.write(get2(chunk, 0));
157                     out.write(get3(chunk, 0));
158                 }
159                 ready = 0;
160             }
161         }
162         if (ready != 0)
163             throw new Base64FormatException("Invalid length.");
164         out.flush();
165     }
166
167     /**
168      * Do the decoding, and return a String.
169      * This methods should be called when the decoder is used in
170      * <em>String</em> mode. It decodes the input string to an output string
171      * that is returned.
172      * @exception RuntimeException If the object wasn't constructed to
173      * decode a String.
174      * @exception Base64FormatException If the input string is not compliant
175      * with the BASE64 specification.
176      */

177     public String JavaDoc processString() throws Base64FormatException
178     {
179         if (!stringp)
180             throw new RuntimeException JavaDoc(
181                 this.getClass().getName()
182                     + "[processString]"
183                     + "invalid call (not a String)");
184         try
185         {
186             process();
187         }
188         catch (IOException JavaDoc e)
189         {
190         }
191         String JavaDoc s;
192         try
193         {
194             s = ((ByteArrayOutputStream JavaDoc) out).toString("ISO-8859-1");
195         }
196         catch (UnsupportedEncodingException JavaDoc ex)
197         {
198             throw new RuntimeException JavaDoc(
199                 this.getClass().getName()
200                     + "[processString] Unable to convert"
201                     + "properly char to bytes");
202         }
203         return s;
204     }
205
206     /**
207      * Create a decoder to decode a String.
208      * @param input The string to be decoded.
209      */

210     public Base64Decoder(String JavaDoc input)
211     {
212         byte bytes[];
213         try
214         {
215             bytes = input.getBytes("ISO-8859-1");
216         }
217         catch (UnsupportedEncodingException JavaDoc ex)
218         {
219             throw new RuntimeException JavaDoc(
220                 this.getClass().getName()
221                     + "[Constructor] Unable to convert"
222                     + "properly char to bytes");
223         }
224         this.stringp = true;
225         this.in = new ByteArrayInputStream JavaDoc(bytes);
226         this.out = new ByteArrayOutputStream JavaDoc();
227     }
228
229     /**
230      * Create a decoder to decode a stream.
231      * @param in The input stream (to be decoded).
232      * @param out The output stream, to write decoded data to.
233      */

234     public Base64Decoder(InputStream JavaDoc in, OutputStream JavaDoc out)
235     {
236         this.in = in;
237         this.out = out;
238         this.stringp = false;
239     }
240
241     /**
242      * Test the decoder.
243      * Run it with one argument: the string to be decoded, it will print out
244      * the decoded value.
245      */

246     public static void main(String JavaDoc args[])
247     {
248         if (args.length == 1)
249         {
250             try
251             {
252                 Base64Decoder b = new Base64Decoder(args[0]);
253                 System.out.println("[" + b.processString() + "]");
254             }
255             catch (Base64FormatException e)
256             {
257                 System.out.println("Invalid Base64 format !");
258                 System.exit(1);
259             }
260         }
261         else if ((args.length == 2) && (args[0].equals("-f")))
262         {
263             try
264             {
265                 FileInputStream JavaDoc in = new FileInputStream JavaDoc(args[1]);
266                 Base64Decoder b = new Base64Decoder(in, System.out);
267                 b.process();
268             }
269             catch (Exception JavaDoc ex)
270             {
271                 System.out.println("error: " + ex.getMessage());
272                 System.exit(1);
273             }
274         }
275         else
276         {
277             System.out.println("Base64Decoder [strong] [-f file]");
278         }
279         System.exit(0);
280     }
281 }
282
Popular Tags