View Javadoc

1   package com.atlassian.user.util;
2   
3   /**
4    *  Copied across from OSUser
5    */
6   
7   public final class Base64Encoder
8   {
9       //~ Static fields/initializers /////////////////////////////////////////////
10  
11      // BASE64 encode_table
12      private final static char[] enc_table = {
13          'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
14          'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
15          'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
16          'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
17          '4', '5', '6', '7', '8', '9', '+', '/'
18      };
19  
20      // BASE64 decode_table
21      private final static byte[] dec_table = {
22          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
23          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
24          -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57,
25          58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
26          10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1,
27          -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
28          40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1,
29          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
30          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
31          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
32          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
33          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
34          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
35          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36          -1,
37      };
38  
39      //~ Methods ////////////////////////////////////////////////////////////////
40  
41      public static byte[] decode(byte[] data) {
42          int padCount = 0;
43          int i;
44          int len = data.length;
45          int real_len = 0;
46  
47          for (i = len - 1; i >= 0; --i) {
48              if (data[i] > ' ') {
49                  real_len++;
50              }
51  
52              if (data[i] == 0x3D) {
53                  padCount++;
54              }
55          }
56  
57          if ((real_len % 4) != 0) {
58              throw new IllegalArgumentException("Length not a multiple of 4");
59          }
60  
61          int ret_len = ((real_len / 4) * 3) - padCount;
62          byte[] ret = new byte[ret_len];
63  
64          i = 0;
65  
66          byte[] t = new byte[4];
67          int output_index = 0;
68          int j = 0;
69          t[0] = t[1] = t[2] = t[3] = 0x3D;
70  
71          while (i < len) {
72              byte c = data[i++];
73  
74              if (c > ' ') {
75                  t[j++] = c;
76              }
77  
78              if (j == 4) {
79                  output_index += decode(ret, output_index, t[0], t[1], t[2], t[3]);
80                  j = 0;
81                  t[0] = t[1] = t[2] = t[3] = 0x3D;
82              }
83          }
84  
85          if (j > 0) {
86              decode(ret, output_index, t[0], t[1], t[2], t[3]);
87          }
88  
89          return ret;
90      }
91  
92      public static int decode(byte[] ret, int ret_off, byte a, byte b, byte c, byte d) {
93          byte da = dec_table[a];
94          byte db = dec_table[b];
95          byte dc = dec_table[c];
96          byte dd = dec_table[d];
97  
98          if ((da == -1) || (db == -1) || ((dc == -1) && (c != 0x3D)) || ((dd == -1) && (d != 0x3D))) {
99              throw new IllegalArgumentException("Invalid character [" + (a & 0xFF) + ", " + (b & 0xFF) + ", " + (c & 0xFF) + ", " + (d & 0xFF) + "]");
100         }
101 
102         ret[ret_off++] = (byte) ((da << 2) | db >>> 4);
103 
104         if (c == 0x3D) {
105             return 1;
106         }
107 
108         ret[ret_off++] = (byte) ((db << 4) | dc >>> 2);
109 
110         if (d == 0x3D) {
111             return 2;
112         }
113 
114         ret[ret_off++] = (byte) ((dc << 6) | dd);
115 
116         return 3;
117     }
118 
119     public static byte[] encode(byte[] data) {
120         int i = 0;
121         int j = 0;
122         int len = data.length;
123         int delta = len % 3;
124         int outlen = (((len + 2) / 3) * 4) + ((len == 0) ? 2 : 0);
125         byte[] output = new byte[outlen];
126 
127         byte a;
128         byte b;
129         byte c;
130 
131         for (int count = len / 3; count > 0; count--) {
132             a = data[i++];
133             b = data[i++];
134             c = data[i++];
135             output[j++] = (byte) (enc_table[(a >>> 2) & 0x3F]);
136             output[j++] = (byte) (enc_table[((a << 4) & 0x30) + ((b >>> 4) & 0x0F)]);
137             output[j++] = (byte) (enc_table[((b << 2) & 0x3C) + ((c >>> 6) & 0x03)]);
138             output[j++] = (byte) (enc_table[c & 0x3F]);
139         }
140 
141         if (delta == 1) {
142             a = data[i++];
143             output[j++] = (byte) (enc_table[(a >>> 2) & 0x3F]);
144             output[j++] = (byte) (enc_table[((a << 4) & 0x30)]);
145             output[j++] = (byte) '=';
146             output[j++] = (byte) '=';
147         } else if (delta == 2) {
148             a = data[i++];
149             b = data[i++];
150             output[j++] = (byte) (enc_table[(a >>> 2) & 0x3F]);
151             output[j++] = (byte) (enc_table[((a << 4) & 0x30) + ((b >>> 4) & 0x0F)]);
152             output[j++] = (byte) (enc_table[((b << 2) & 0x3C)]);
153             output[j++] = (byte) '=';
154         }
155 
156         if (j != outlen) {
157             throw new IllegalArgumentException("output length was not the expected");
158         }
159 
160         return output;
161     }
162 }