KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > mail > util > Base64InputStream


1 /*
2  * Base64InputStream.java
3  * Copyright (C) 2002 The Free Software Foundation
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 package gnu.mail.util;
21
22 import java.io.*;
23
24 /**
25  * A Base64 content transfer encoding filter stream.
26  * <p>
27  * From RFC 2045, section 6.8:
28  * <p>
29  * The Base64 Content-Transfer-Encoding is designed to represent
30  * arbitrary sequences of octets in a form that need not be humanly
31  * readable. The encoding and decoding algorithms are simple, but the
32  * encoded data are consistently only about 33 percent larger than the
33  * unencoded data.
34  *
35  * @author <a HREF="mailto:dog@gnu.org">Chris Burdess</a>
36  */

37 public class Base64InputStream
38   extends FilterInputStream
39 {
40
41   private byte[] buffer;
42   private int buflen;
43   private int index;
44   private byte[] decodeBuf;
45
46   private static final char[] src =
47   {
48     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
49     'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
50     'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
51     'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
52     'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
53     'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
54     '8', '9', '+', '/'
55   };
56   private static final byte[] dst;
57   
58   private static final int LF = 10, CR = 13, EQ = 61;
59   
60   static
61   {
62     dst = new byte[256];
63     for (int i = 0; i<255; i++)
64       dst[i] = -1;
65     for (int i = 0; i<src.length; i++)
66       dst[src[i]] = (byte)i;
67     
68   }
69   
70   /**
71    * Constructs an input stream that decodes an underlying Base64-encoded
72    * stream.
73    * @param in the Base64-encoded stream
74    */

75   public Base64InputStream(InputStream in)
76   {
77     super(in);
78     decodeBuf = new byte[4];
79     buffer = new byte[3];
80   }
81   
82   /**
83    * Reads the next byte of data from the input stream.
84    */

85   public int read()
86     throws IOException
87   {
88     if (index>=buflen)
89     {
90       decode();
91       if (buflen==0)
92         return -1;
93       index = 0;
94     }
95     return buffer[index++] & 0xff;
96   }
97   
98   /**
99    * Reads up to len bytes of data from the input stream into an array of
100    * bytes.
101    */

102   public int read(byte[] b, int off, int len)
103     throws IOException
104   {
105     try
106     {
107       int l = 0;
108       for (; l<len; l++)
109       {
110         int c;
111         if ((c=read())==-1)
112         {
113           if (l==0)
114             l = -1;
115           break;
116         }
117         b[off+l] = (byte)c;
118       }
119       return l;
120     }
121     catch (IOException e)
122     {
123       return -1;
124     }
125   }
126
127   /**
128    * Returns the number of bytes that can be read (or skipped over) from this
129    * input stream without blocking by the next caller of a method for this
130    * input stream.
131    */

132   public int available()
133     throws IOException
134   {
135     return (in.available()*3)/4+(buflen-index);
136   }
137   
138   private void decode()
139     throws IOException
140   {
141     buflen = 0;
142     int c;
143     do
144     {
145       c = in.read();
146       if (c==-1)
147         return;
148     }
149     while (c==LF || c==CR);
150     decodeBuf[0] = (byte)c;
151     int j = 3, l;
152     for (int k=1; (l=in.read(decodeBuf, k, j))!=j; k += l)
153     {
154       if (l==-1)
155         throw new IOException("Base64 encoding error");
156       j -= l;
157     }
158     
159     byte b0 = dst[decodeBuf[0] & 0xff];
160     byte b2 = dst[decodeBuf[1] & 0xff];
161     buffer[buflen++] = (byte)(b0<<2 & 0xfc | b2>>>4 & 0x3);
162     if (decodeBuf[2]!=EQ)
163     {
164       b0 = b2;
165       b2 = dst[decodeBuf[2] & 0xff];
166       buffer[buflen++] = (byte)(b0<<4 & 0xf0 | b2>>>2 & 0xf);
167       if (decodeBuf[3]!=EQ)
168       {
169         byte b1 = b2;
170         b2 = dst[decodeBuf[3] & 0xff];
171         buffer[buflen++] = (byte)(b1<<6 & 0xc0 | b2 & 0x3f);
172       }
173     }
174   }
175
176 }
177
Popular Tags