1   /*
2    * Copyright 2000-2001,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  /* 
18  
19   */
20  
21  package org.apache.wsrp4j.producer.util;
22  
23  /*
24   * The Apache Software License, Version 1.1
25   *
26   *
27   * Copyright (c) 2001 The Apache Software Foundation.  All rights
28   * reserved.
29   *
30   * Redistribution and use in source and binary forms, with or without
31   * modification, are permitted provided that the following conditions
32   * are met:
33   *
34   * 1. Redistributions of source code must retain the above copyright
35   *    notice, this list of conditions and the following disclaimer. 
36   *
37   * 2. Redistributions in binary form must reproduce the above copyright
38   *    notice, this list of conditions and the following disclaimer in
39   *    the documentation and/or other materials provided with the
40   *    distribution.
41   *
42   * 3. The end-user documentation included with the redistribution,
43   *    if any, must include the following acknowledgment:  
44   *       "This product includes software developed by the
45   *        Apache Software Foundation (http://www.apache.org/)."
46   *    Alternately, this acknowledgment may appear in the software itself,
47   *    if and wherever such third-party acknowledgments normally appear.
48   *
49   * 4. The names "Axis" and "Apache Software Foundation" must
50   *    not be used to endorse or promote products derived from this
51   *    software without prior written permission. For written 
52   *    permission, please contact apache@apache.org.
53   *
54   * 5. Products derived from this software may not be called "Apache",
55   *    nor may "Apache" appear in their name, without prior written
56   *    permission of the Apache Software Foundation.
57   *
58   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
59   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
61   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
62   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
63   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
64   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
65   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
66   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
67   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
68   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69   * SUCH DAMAGE.
70   * ====================================================================
71   *
72   * This software consists of voluntary contributions made by many
73   * individuals on behalf of the Apache Software Foundation.  For more
74   * information on the Apache Software Foundation, please see
75   * <http://www.apache.org/>.
76   */
77  
78  import java.io.IOException;
79  import java.io.OutputStream;
80  import java.io.Writer;
81  
82  import org.apache.axis.utils.Messages;
83  
84  /**
85   * This is taken from the axis source tree. 
86   * Just adapted the base64 alphaphet for use in url's.  
87   * 
88   *
89   * @author TAMURA Kent &lt;kent@trl.ibm.co.jp&gt;
90   */
91  public class Base64 {
92      private static final char[] S_BASE64CHAR = { 'A', 'B', 'C', 'D', 'E', 'F',
93              'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
94              'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
95              'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
96              't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
97              '6', '7', '8', '9', '-', '_' };
98  
99      private static final char S_BASE64PAD = '*';
100 
101     private static final byte[] S_DECODETABLE = new byte[128];
102     static {
103         for (int i = 0; i < S_DECODETABLE.length; i++)
104             S_DECODETABLE[i] = Byte.MAX_VALUE; // 127
105         for (int i = 0; i < S_BASE64CHAR.length; i++)
106             // 0 to 63
107             S_DECODETABLE[S_BASE64CHAR[i]] = (byte) i;
108     }
109 
110     private static int decode0(char[] ibuf, byte[] obuf, int wp) {
111         int outlen = 3;
112         if (ibuf[3] == S_BASE64PAD)
113             outlen = 2;
114         if (ibuf[2] == S_BASE64PAD)
115             outlen = 1;
116         int b0 = S_DECODETABLE[ibuf[0]];
117         int b1 = S_DECODETABLE[ibuf[1]];
118         int b2 = S_DECODETABLE[ibuf[2]];
119         int b3 = S_DECODETABLE[ibuf[3]];
120         switch (outlen) {
121         case 1:
122             obuf[wp] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3);
123             return 1;
124         case 2:
125             obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3);
126             obuf[wp] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf);
127             return 2;
128         case 3:
129             obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3);
130             obuf[wp++] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf);
131             obuf[wp] = (byte) (b2 << 6 & 0xc0 | b3 & 0x3f);
132             return 3;
133         default:
134             throw new RuntimeException(Messages.getMessage("internalError00"));
135         }
136     }
137 
138     /**
139      *
140      */
141     public static byte[] decode(char[] data, int off, int len) {
142         char[] ibuf = new char[4];
143         int ibufcount = 0;
144         byte[] obuf = new byte[len / 4 * 3 + 3];
145         int obufcount = 0;
146         for (int i = off; i < off + len; i++) {
147             char ch = data[i];
148             if (ch == S_BASE64PAD || ch < S_DECODETABLE.length
149                     && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
150                 ibuf[ibufcount++] = ch;
151                 if (ibufcount == ibuf.length) {
152                     ibufcount = 0;
153                     obufcount += decode0(ibuf, obuf, obufcount);
154                 }
155             }
156         }
157         if (obufcount == obuf.length)
158             return obuf;
159         byte[] ret = new byte[obufcount];
160         System.arraycopy(obuf, 0, ret, 0, obufcount);
161         return ret;
162     }
163 
164     /**
165      *
166      */
167     public static byte[] decode(String data) {
168         char[] ibuf = new char[4];
169         int ibufcount = 0;
170         byte[] obuf = new byte[data.length() / 4 * 3 + 3];
171         int obufcount = 0;
172         for (int i = 0; i < data.length(); i++) {
173             char ch = data.charAt(i);
174             if (ch == S_BASE64PAD || ch < S_DECODETABLE.length
175                     && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
176                 ibuf[ibufcount++] = ch;
177                 if (ibufcount == ibuf.length) {
178                     ibufcount = 0;
179                     obufcount += decode0(ibuf, obuf, obufcount);
180                 }
181             }
182         }
183         if (obufcount == obuf.length)
184             return obuf;
185         byte[] ret = new byte[obufcount];
186         System.arraycopy(obuf, 0, ret, 0, obufcount);
187         return ret;
188     }
189 
190     /**
191      *
192      */
193     public static void decode(char[] data, int off, int len,
194             OutputStream ostream) throws IOException {
195         char[] ibuf = new char[4];
196         int ibufcount = 0;
197         byte[] obuf = new byte[3];
198         for (int i = off; i < off + len; i++) {
199             char ch = data[i];
200             if (ch == S_BASE64PAD || ch < S_DECODETABLE.length
201                     && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
202                 ibuf[ibufcount++] = ch;
203                 if (ibufcount == ibuf.length) {
204                     ibufcount = 0;
205                     int obufcount = decode0(ibuf, obuf, 0);
206                     ostream.write(obuf, 0, obufcount);
207                 }
208             }
209         }
210     }
211 
212     /**
213      *
214      */
215     public static void decode(String data, OutputStream ostream)
216             throws IOException {
217         char[] ibuf = new char[4];
218         int ibufcount = 0;
219         byte[] obuf = new byte[3];
220         for (int i = 0; i < data.length(); i++) {
221             char ch = data.charAt(i);
222             if (ch == S_BASE64PAD || ch < S_DECODETABLE.length
223                     && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
224                 ibuf[ibufcount++] = ch;
225                 if (ibufcount == ibuf.length) {
226                     ibufcount = 0;
227                     int obufcount = decode0(ibuf, obuf, 0);
228                     ostream.write(obuf, 0, obufcount);
229                 }
230             }
231         }
232     }
233 
234     /**
235      * Returns base64 representation of specified byte array.
236      */
237     public static String encode(byte[] data) {
238         return encode(data, 0, data.length);
239     }
240 
241     /**
242      * Returns base64 representation of specified byte array.
243      */
244     public static String encode(byte[] data, int off, int len) {
245         if (len <= 0)
246             return "";
247         char[] out = new char[len / 3 * 4 + 4];
248         int rindex = off;
249         int windex = 0;
250         int rest = len - off;
251         while (rest >= 3) {
252             int i = ((data[rindex] & 0xff) << 16)
253                     + ((data[rindex + 1] & 0xff) << 8)
254                     + (data[rindex + 2] & 0xff);
255             out[windex++] = S_BASE64CHAR[i >> 18];
256             out[windex++] = S_BASE64CHAR[(i >> 12) & 0x3f];
257             out[windex++] = S_BASE64CHAR[(i >> 6) & 0x3f];
258             out[windex++] = S_BASE64CHAR[i & 0x3f];
259             rindex += 3;
260             rest -= 3;
261         }
262         if (rest == 1) {
263             int i = data[rindex] & 0xff;
264             out[windex++] = S_BASE64CHAR[i >> 2];
265             out[windex++] = S_BASE64CHAR[(i << 4) & 0x3f];
266             out[windex++] = S_BASE64PAD;
267             out[windex++] = S_BASE64PAD;
268         }
269         else if (rest == 2) {
270             int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff);
271             out[windex++] = S_BASE64CHAR[i >> 10];
272             out[windex++] = S_BASE64CHAR[(i >> 4) & 0x3f];
273             out[windex++] = S_BASE64CHAR[(i << 2) & 0x3f];
274             out[windex++] = S_BASE64PAD;
275         }
276         return new String(out, 0, windex);
277     }
278 
279     /**
280      * Outputs base64 representation of the specified byte array to a byte stream.
281      */
282     public static void encode(byte[] data, int off, int len,
283             OutputStream ostream) throws IOException {
284         if (len <= 0)
285             return;
286         byte[] out = new byte[4];
287         int rindex = off;
288         int rest = len - off;
289         while (rest >= 3) {
290             int i = ((data[rindex] & 0xff) << 16)
291                     + ((data[rindex + 1] & 0xff) << 8)
292                     + (data[rindex + 2] & 0xff);
293             out[0] = (byte) S_BASE64CHAR[i >> 18];
294             out[1] = (byte) S_BASE64CHAR[(i >> 12) & 0x3f];
295             out[2] = (byte) S_BASE64CHAR[(i >> 6) & 0x3f];
296             out[3] = (byte) S_BASE64CHAR[i & 0x3f];
297             ostream.write(out, 0, 4);
298             rindex += 3;
299             rest -= 3;
300         }
301         if (rest == 1) {
302             int i = data[rindex] & 0xff;
303             out[0] = (byte) S_BASE64CHAR[i >> 2];
304             out[1] = (byte) S_BASE64CHAR[(i << 4) & 0x3f];
305             out[2] = (byte) S_BASE64PAD;
306             out[3] = (byte) S_BASE64PAD;
307             ostream.write(out, 0, 4);
308         }
309         else if (rest == 2) {
310             int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff);
311             out[0] = (byte) S_BASE64CHAR[i >> 10];
312             out[1] = (byte) S_BASE64CHAR[(i >> 4) & 0x3f];
313             out[2] = (byte) S_BASE64CHAR[(i << 2) & 0x3f];
314             out[3] = (byte) S_BASE64PAD;
315             ostream.write(out, 0, 4);
316         }
317     }
318 
319     /**
320      * Outputs base64 representation of the specified byte array to a character stream.
321      */
322     public static void encode(byte[] data, int off, int len, Writer writer)
323             throws IOException {
324         if (len <= 0)
325             return;
326         char[] out = new char[4];
327         int rindex = off;
328         int rest = len - off;
329         int output = 0;
330         while (rest >= 3) {
331             int i = ((data[rindex] & 0xff) << 16)
332                     + ((data[rindex + 1] & 0xff) << 8)
333                     + (data[rindex + 2] & 0xff);
334             out[0] = S_BASE64CHAR[i >> 18];
335             out[1] = S_BASE64CHAR[(i >> 12) & 0x3f];
336             out[2] = S_BASE64CHAR[(i >> 6) & 0x3f];
337             out[3] = S_BASE64CHAR[i & 0x3f];
338             writer.write(out, 0, 4);
339             rindex += 3;
340             rest -= 3;
341             output += 4;
342             if (output % 76 == 0)
343                 writer.write("\n");
344         }
345         if (rest == 1) {
346             int i = data[rindex] & 0xff;
347             out[0] = S_BASE64CHAR[i >> 2];
348             out[1] = S_BASE64CHAR[(i << 4) & 0x3f];
349             out[2] = S_BASE64PAD;
350             out[3] = S_BASE64PAD;
351             writer.write(out, 0, 4);
352         }
353         else if (rest == 2) {
354             int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff);
355             out[0] = S_BASE64CHAR[i >> 10];
356             out[1] = S_BASE64CHAR[(i >> 4) & 0x3f];
357             out[2] = S_BASE64CHAR[(i << 2) & 0x3f];
358             out[3] = S_BASE64PAD;
359             writer.write(out, 0, 4);
360         }
361     }
362 }