• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17 
18 /*
19  * NOTE: This class copied from the Android Open Source Project:
20  * dalvik/libcore/luni/src/main/java/org/apache/harmony/luni/util/Base64.java
21  */
22 
23 /**
24 * @author Alexander Y. Kleymenov
25 * @version $Revision$
26 */
27 
28 package com.google.polo.wire.json;
29 
30 import java.io.UnsupportedEncodingException;
31 
32 /**
33  * This class implements Base64 encoding/decoding functionality
34  * as specified in RFC 2045 (http://www.ietf.org/rfc/rfc2045.txt).
35  */
36 public class Base64 {
37 
decode(byte[] in)38     public static byte[] decode(byte[] in) {
39         return decode(in, in.length);
40     }
41 
decode(byte[] in, int len)42     public static byte[] decode(byte[] in, int len) {
43         // approximate output length
44         int length = len / 4 * 3;
45         // return an empty array on emtpy or short input without padding
46         if (length == 0) {
47             return new byte[0];
48         }
49         // temporary array
50         byte[] out = new byte[length];
51         // number of padding characters ('=')
52         int pad = 0;
53         byte chr;
54         // compute the number of the padding characters
55         // and adjust the length of the input
56         for (;;len--) {
57             chr = in[len-1];
58             // skip the neutral characters
59             if ((chr == '\n') || (chr == '\r') ||
60                     (chr == ' ') || (chr == '\t')) {
61                 continue;
62             }
63             if (chr == '=') {
64                 pad++;
65             } else {
66                 break;
67             }
68         }
69         // index in the output array
70         int out_index = 0;
71         // index in the input array
72         int in_index = 0;
73         // holds the value of the input character
74         int bits = 0;
75         // holds the value of the input quantum
76         int quantum = 0;
77         for (int i=0; i<len; i++) {
78             chr = in[i];
79             // skip the neutral characters
80             if ((chr == '\n') || (chr == '\r') ||
81                     (chr == ' ') || (chr == '\t')) {
82                 continue;
83             }
84             if ((chr >= 'A') && (chr <= 'Z')) {
85                 // char ASCII value
86                 //  A    65    0
87                 //  Z    90    25 (ASCII - 65)
88                 bits = chr - 65;
89             } else if ((chr >= 'a') && (chr <= 'z')) {
90                 // char ASCII value
91                 //  a    97    26
92                 //  z    122   51 (ASCII - 71)
93                 bits = chr - 71;
94             } else if ((chr >= '0') && (chr <= '9')) {
95                 // char ASCII value
96                 //  0    48    52
97                 //  9    57    61 (ASCII + 4)
98                 bits = chr + 4;
99             } else if (chr == '+') {
100                 bits = 62;
101             } else if (chr == '/') {
102                 bits = 63;
103             } else {
104                 return null;
105             }
106             // append the value to the quantum
107             quantum = (quantum << 6) | (byte) bits;
108             if (in_index%4 == 3) {
109                 // 4 characters were read, so make the output:
110                 out[out_index++] = (byte) ((quantum & 0x00FF0000) >> 16);
111                 out[out_index++] = (byte) ((quantum & 0x0000FF00) >> 8);
112                 out[out_index++] = (byte) (quantum & 0x000000FF);
113             }
114             in_index++;
115         }
116         if (pad > 0) {
117             // adjust the quantum value according to the padding
118             quantum = quantum << (6*pad);
119             // make output
120             out[out_index++] = (byte) ((quantum & 0x00FF0000) >> 16);
121             if (pad == 1) {
122                 out[out_index++] = (byte) ((quantum & 0x0000FF00) >> 8);
123             }
124         }
125         // create the resulting array
126         byte[] result = new byte[out_index];
127         System.arraycopy(out, 0, result, 0, out_index);
128         return result;
129     }
130 
131     private static final byte[] map = new byte[]
132         {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
133          'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
134          'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
135          'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
136          '4', '5', '6', '7', '8', '9', '+', '/'};
137 
encode(byte[] in, String charsetName)138     public static String encode(byte[] in, String charsetName) throws UnsupportedEncodingException {
139         int length = in.length * 4 / 3;
140         length += length / 76 + 3; // for crlr
141         byte[] out = new byte[length];
142         int index = 0, i, crlr = 0, end = in.length - in.length%3;
143         for (i=0; i<end; i+=3) {
144             out[index++] = map[(in[i] & 0xff) >> 2];
145             out[index++] = map[((in[i] & 0x03) << 4)
146                                 | ((in[i+1] & 0xff) >> 4)];
147             out[index++] = map[((in[i+1] & 0x0f) << 2)
148                                 | ((in[i+2] & 0xff) >> 6)];
149             out[index++] = map[(in[i+2] & 0x3f)];
150             if (((index - crlr)%76 == 0) && (index != 0)) {
151                 out[index++] = '\n';
152                 crlr++;
153                 //out[index++] = '\r';
154                 //crlr++;
155             }
156         }
157         switch (in.length % 3) {
158             case 1:
159                 out[index++] = map[(in[end] & 0xff) >> 2];
160                 out[index++] = map[(in[end] & 0x03) << 4];
161                 out[index++] = '=';
162                 out[index++] = '=';
163                 break;
164             case 2:
165                 out[index++] = map[(in[end] & 0xff) >> 2];
166                 out[index++] = map[((in[end] & 0x03) << 4)
167                                     | ((in[end+1] & 0xff) >> 4)];
168                 out[index++] = map[((in[end+1] & 0x0f) << 2)];
169                 out[index++] = '=';
170                 break;
171         }
172         return new String(out, 0, index, charsetName);
173     }
174 }
175 
176