View Javadoc

1   package com.sun.syndication.io.impl;
2   
3   /*
4    * Copyright 2004 Sun Microsystems, Inc.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   *
18   */
19  
20  import java.io.UnsupportedEncodingException;
21  
22  /***
23   * Encodes/decodes byte arrays and Strings into/from a base 64 String.
24   * <p>
25   * @author Alejandro Abdelnur
26   *
27   */
28  public class Base64 {
29  
30      /***
31       * Encodes a String into a base 64 String. The resulting encoding is chunked at 76 bytes.
32       * <p>
33       * @param s String to encode.
34       * @return encoded string.
35       *
36       */
37      public static String encode(String s) {
38          byte[] sBytes =  s.getBytes();
39          sBytes = encode(sBytes);
40          s = new String(sBytes);
41          return s;
42      }
43  
44      /***
45       * Decodes a base 64 String into a String.
46       * <p>
47       * @param s String to decode.
48       * @return encoded string.
49       * @throws java.lang.IllegalArgumentException thrown if the given byte array was not valid com.sun.syndication.io.impl.Base64 encoding.
50       *
51       */
52      public static String decode(String s) throws IllegalArgumentException {
53          byte[] sBytes = s.getBytes();
54          sBytes = decode(sBytes);
55          s = new String(sBytes);
56          return s;
57      }
58  
59  
60      private static final byte[] ALPHASET =
61          "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".getBytes();
62  
63      private static final int I6O2 = 255 - 3;
64      private static final int O6I2 = 3;
65      private static final int I4O4 = 255 - 15;
66      private static final int O4I4 = 15;
67      private static final int I2O6 = 255 - 63;
68      private static final int O2I6 = 63;
69  
70      /***
71       * Encodes a byte array into a base 64 byte array.
72       * <p>
73       * @param dData byte array to encode.
74       * @return encoded byte array.
75       *
76       */
77      public static byte[] encode(byte[] dData) {
78          if (dData==null) {
79              throw new IllegalArgumentException("Cannot encode null");
80          }
81          byte[] eData = new byte[((dData.length+2)/3)*4];
82  
83          int eIndex = 0;
84          for (int i = 0; i<dData.length; i += 3) {
85              int d1;
86              int d2=0;
87              int d3=0;
88              int e1;
89              int e2;
90              int e3;
91              int e4;
92              int pad=0;
93  
94              d1 = dData[i];
95              if ((i+1)<dData.length) {
96                  d2 = dData[i+1];
97                  if ((i+2)<dData.length) {
98                      d3 = dData[i+2];
99                  }
100                 else {
101                     pad =1;
102                 }
103             }
104             else {
105                 pad =2;
106             }
107 
108             e1 = ALPHASET[(d1&I6O2)>>2];
109             e2 = ALPHASET[(d1&O6I2)<<4 | (d2&I4O4)>>4];
110             e3 = ALPHASET[(d2&O4I4)<<2 | (d3&I2O6)>>6];
111             e4 = ALPHASET[(d3&O2I6)];
112 
113             eData[eIndex++] = (byte)e1;
114             eData[eIndex++] = (byte)e2;
115             eData[eIndex++] = (pad<2) ?(byte)e3 : (byte)'=';
116             eData[eIndex++] = (pad<1) ?(byte)e4 : (byte)'=';
117 
118         }
119         return eData;
120     }
121 
122     private final static int[] CODES = new int[256];
123 
124     static {
125         for (int i=0;i<CODES.length;i++) {
126             CODES[i] = 64;
127         }
128         for (int i=0;i<ALPHASET.length;i++) {
129             CODES[ALPHASET[i]] = i;
130         }
131     }
132 
133     /***
134      * Dencodes a com.sun.syndication.io.impl.Base64 byte array.
135      * <p>
136      * @param eData byte array to decode.
137      * @return decoded byte array.
138      * @throws java.lang.IllegalArgumentException thrown if the given byte array was not valid com.sun.syndication.io.impl.Base64 encoding.
139      *
140      */
141     public static byte[] decode(byte[] eData) {
142         if (eData==null) {
143             throw new IllegalArgumentException("Cannot decode null");
144         }
145         byte[] cleanEData = (byte[]) eData.clone();
146         int cleanELength = 0;
147         for (int i=0;i<eData.length;i++) {
148             if (eData[i]<256 && CODES[eData[i]]<64) {
149                 cleanEData[cleanELength++] = eData[i];
150             }
151         }
152 
153         int dLength = (cleanELength/4)*3;
154         switch (cleanELength%4) {
155             case 3:
156                 dLength += 2;
157                 break;
158             case 2:
159                 dLength++;
160                 break;
161         }
162 
163         byte[] dData = new byte[dLength];
164         int dIndex = 0;
165         for (int i=0;i<cleanELength;i+=4) {
166             if ((i+3)>cleanELength) {
167                 throw new IllegalArgumentException("byte array is not a valid com.sun.syndication.io.impl.Base64 encoding");
168             }
169             int e1 = CODES[cleanEData[i]];
170             int e2 = CODES[cleanEData[i+1]];
171             int e3 = CODES[cleanEData[i+2]];
172             int e4 = CODES[cleanEData[i+3]];
173             dData[dIndex++] = (byte) ((e1<<2)|(e2>>4));
174             if (dIndex<dData.length) {
175                 dData[dIndex++] = (byte) ((e2<<4) | (e3>>2));
176             }
177             if (dIndex<dData.length) {
178                 dData[dIndex++] = (byte) ((e3<<6) | (e4));
179             }
180         }
181         return dData;
182     }
183 
184     public static void main(String[] args) throws Exception {
185         String s =
186                 "\nPGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+V2UncmUgcHJvcG9zaW5nIDxhIGhy\n"+
187 "ZWY9Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbS9jb3Jwb3JhdGUvc29mdHdhcmVfcHJpbmNpcGxlcy5odG1sIj5z\n"+
188 "b21lIGd1aWRlbGluZXMgPC9hPnRvIGhlbHAgY3VyYiB0aGUgcHJvYmxlbSBvZiBJbnRlcm5ldCBzb2Z0d2Fy\n"+
189 "ZSB0aGF0IGluc3RhbGxzIGl0c2VsZiB3aXRob3V0IHRlbGxpbmcgeW91LCBvciBiZWhhdmVzIGJhZGx5IG9u\n"+
190 "Y2UgaXQgZ2V0cyBvbiB5b3VyIGNvbXB1dGVyLiBXZSd2ZSBiZWVuIGhlYXJpbmcgYSBsb3Qgb2YgY29tcGxh\n"+
191 "aW50cyBhYm91dCB0aGlzIGxhdGVseSBhbmQgaXQgc2VlbXMgdG8gYmUgZ2V0dGluZyB3b3JzZS4gV2UgdGhp\n"+
192 "bmsgaXQncyBpbXBvcnRhbnQgdGhhdCB5b3UgcmV0YWluIGNvbnRyb2wgb2YgeW91ciBjb21wdXRlciBhbmQg\n"+
193 "dGhhdCB0aGVyZSBiZSBzb21lIGNsZWFyIHN0YW5kYXJkcyBpbiBvdXIgaW5kdXN0cnkuIExldCB1cyBrbm93\n"+
194 "IGlmIHlvdSB0aGluayB0aGVzZSBndWlkZWxpbmVzIGFyZSB1c2VmdWwgb3IgaWYgeW91IGhhdmUgc3VnZ2Vz\n"+
195 "dGlvbnMgdG8gaW1wcm92ZSB0aGVtLgo8YnIgLz4KPGJyIC8+Sm9uYXRoYW4gUm9zZW5iZXJnCjxiciAvPgo8\n"+
196 "L2Rpdj4K\n";
197 
198         System.out.println(decode(s));
199     }
200 }
201