001package net.gdface.utils; 002 003import java.io.IOException; 004import java.io.OutputStream; 005import java.io.Writer; 006 007/** 008 * copy from org.apache.axiom.util.base64.Base64Utils(axiom-api-1.2.13.jar) 009 * 010 */ 011public class Base64Utils { 012 private static final char[] S_BASE64CHAR = { 'A', 'B', 'C', 'D', 'E', 'F', 013 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 014 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 015 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 016 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', 017 '6', '7', '8', '9', '+', '/' }; 018 019 private static final char S_BASE64PAD = '='; 020 021 private static final byte[] S_DECODETABLE = new byte[128]; 022 023 static { 024 for (int i = 0; i < S_DECODETABLE.length; i++) 025 S_DECODETABLE[i] = Byte.MAX_VALUE; // 127 026 for (int i = 0; i < S_BASE64CHAR.length; i++) 027 // 0 to 63 028 S_DECODETABLE[S_BASE64CHAR[i]] = (byte) i; 029 } 030 031 private static int decode0(char[] ibuf, byte[] obuf, int wp) { 032 int outlen = 3; 033 if (ibuf[3] == S_BASE64PAD) 034 outlen = 2; 035 if (ibuf[2] == S_BASE64PAD) 036 outlen = 1; 037 int b0 = S_DECODETABLE[ibuf[0]]; 038 int b1 = S_DECODETABLE[ibuf[1]]; 039 int b2 = S_DECODETABLE[ibuf[2]]; 040 int b3 = S_DECODETABLE[ibuf[3]]; 041 switch (outlen) { 042 case 1: 043 obuf[wp] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); 044 return 1; 045 case 2: 046 obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); 047 obuf[wp] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf); 048 return 2; 049 case 3: 050 obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3); 051 obuf[wp++] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf); 052 obuf[wp] = (byte) (b2 << 6 & 0xc0 | b3 & 0x3f); 053 return 3; 054 default: 055 throw new RuntimeException("internalError00"); 056 } 057 } 058 059 /** 060 * 061 */ 062 public static byte[] decode(char[] data, int off, int len) { 063 char[] ibuf = new char[4]; 064 int ibufcount = 0; 065 byte[] obuf = new byte[len / 4 * 3 + 3]; 066 int obufcount = 0; 067 for (int i = off; i < off + len; i++) { 068 char ch = data[i]; 069 if (ch == S_BASE64PAD || ch < S_DECODETABLE.length 070 && S_DECODETABLE[ch] != Byte.MAX_VALUE) { 071 ibuf[ibufcount++] = ch; 072 if (ibufcount == ibuf.length) { 073 ibufcount = 0; 074 obufcount += decode0(ibuf, obuf, obufcount); 075 } 076 } 077 } 078 if (obufcount == obuf.length) 079 return obuf; 080 byte[] ret = new byte[obufcount]; 081 System.arraycopy(obuf, 0, ret, 0, obufcount); 082 return ret; 083 } 084 085 /** 086 * 087 */ 088 public static byte[] decode(String data) { 089 char[] ibuf = new char[4]; 090 int ibufcount = 0; 091 byte[] obuf = new byte[data.length() / 4 * 3 + 3]; 092 int obufcount = 0; 093 for (int i = 0; i < data.length(); i++) { 094 char ch = data.charAt(i); 095 if (ch == S_BASE64PAD || ch < S_DECODETABLE.length 096 && S_DECODETABLE[ch] != Byte.MAX_VALUE) { 097 ibuf[ibufcount++] = ch; 098 if (ibufcount == ibuf.length) { 099 ibufcount = 0; 100 obufcount += decode0(ibuf, obuf, obufcount); 101 } 102 } 103 } 104 if (obufcount == obuf.length) 105 return obuf; 106 byte[] ret = new byte[obufcount]; 107 System.arraycopy(obuf, 0, ret, 0, obufcount); 108 return ret; 109 } 110 111 /** 112 * checks input string for invalid Base64 characters 113 * 114 * @param data 115 * @return true, if String contains only valid Base64 characters. false, otherwise 116 */ 117 public static boolean isValidBase64Encoding(String data) { 118 for (int i = 0; i < data.length(); i++) { 119 char ch = data.charAt(i); 120 121 if (ch == S_BASE64PAD || ch < S_DECODETABLE.length 122 && S_DECODETABLE[ch] != Byte.MAX_VALUE) { 123 //valid character.Do nothing 124 } else if (ch == '\r' || ch == '\n') { 125 //do nothing 126 } else { 127 return false; 128 } 129 }//iterate over all characters in the string 130 return true; 131 } 132 133 134 /** 135 * 136 */ 137 public static void decode(char[] data, int off, int len, 138 OutputStream ostream) throws IOException { 139 char[] ibuf = new char[4]; 140 int ibufcount = 0; 141 byte[] obuf = new byte[3]; 142 for (int i = off; i < off + len; i++) { 143 char ch = data[i]; 144 if (ch == S_BASE64PAD || ch < S_DECODETABLE.length 145 && S_DECODETABLE[ch] != Byte.MAX_VALUE) { 146 ibuf[ibufcount++] = ch; 147 if (ibufcount == ibuf.length) { 148 ibufcount = 0; 149 int obufcount = decode0(ibuf, obuf, 0); 150 ostream.write(obuf, 0, obufcount); 151 } 152 } 153 } 154 } 155 156 /** 157 * 158 */ 159 public static void decode(String data, OutputStream ostream) 160 throws IOException { 161 char[] ibuf = new char[4]; 162 int ibufcount = 0; 163 byte[] obuf = new byte[3]; 164 for (int i = 0; i < data.length(); i++) { 165 char ch = data.charAt(i); 166 if (ch == S_BASE64PAD || ch < S_DECODETABLE.length 167 && S_DECODETABLE[ch] != Byte.MAX_VALUE) { 168 ibuf[ibufcount++] = ch; 169 if (ibufcount == ibuf.length) { 170 ibufcount = 0; 171 int obufcount = decode0(ibuf, obuf, 0); 172 ostream.write(obuf, 0, obufcount); 173 } 174 } 175 } 176 } 177 178 /** Returns base64 representation of specified byte array. */ 179 public static String encode(byte[] data) { 180 return encode(data, 0, data.length); 181 } 182 183 /** Returns base64 representation of specified byte array. */ 184 public static String encode(byte[] data, int off, int len) { 185 if (len <= 0) 186 return ""; 187 char[] out = new char[len / 3 * 4 + 4]; 188 int rindex = off; 189 int windex = 0; 190 int rest = len - off; 191 while (rest >= 3) { 192 int i = ((data[rindex] & 0xff) << 16) 193 + ((data[rindex + 1] & 0xff) << 8) 194 + (data[rindex + 2] & 0xff); 195 out[windex++] = S_BASE64CHAR[i >> 18]; 196 out[windex++] = S_BASE64CHAR[(i >> 12) & 0x3f]; 197 out[windex++] = S_BASE64CHAR[(i >> 6) & 0x3f]; 198 out[windex++] = S_BASE64CHAR[i & 0x3f]; 199 rindex += 3; 200 rest -= 3; 201 } 202 if (rest == 1) { 203 int i = data[rindex] & 0xff; 204 out[windex++] = S_BASE64CHAR[i >> 2]; 205 out[windex++] = S_BASE64CHAR[(i << 4) & 0x3f]; 206 out[windex++] = S_BASE64PAD; 207 out[windex++] = S_BASE64PAD; 208 } else if (rest == 2) { 209 int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); 210 out[windex++] = S_BASE64CHAR[i >> 10]; 211 out[windex++] = S_BASE64CHAR[(i >> 4) & 0x3f]; 212 out[windex++] = S_BASE64CHAR[(i << 2) & 0x3f]; 213 out[windex++] = S_BASE64PAD; 214 } 215 return new String(out, 0, windex); 216 } 217 218 /** Outputs base64 representation of the specified byte array to the specified String Buffer */ 219 public static void encode(byte[] data, int off, int len, StringBuffer buffer) { 220 if (len <= 0) { 221 return; 222 } 223 224 char[] out = new char[4]; 225 int rindex = off; 226 int rest = len - off; 227 while (rest >= 3) { 228 int i = ((data[rindex] & 0xff) << 16) 229 + ((data[rindex + 1] & 0xff) << 8) 230 + (data[rindex + 2] & 0xff); 231 out[0] = S_BASE64CHAR[i >> 18]; 232 out[1] = S_BASE64CHAR[(i >> 12) & 0x3f]; 233 out[2] = S_BASE64CHAR[(i >> 6) & 0x3f]; 234 out[3] = S_BASE64CHAR[i & 0x3f]; 235 buffer.append(out); 236 rindex += 3; 237 rest -= 3; 238 } 239 if (rest == 1) { 240 int i = data[rindex] & 0xff; 241 out[0] = S_BASE64CHAR[i >> 2]; 242 out[1] = S_BASE64CHAR[(i << 4) & 0x3f]; 243 out[2] = S_BASE64PAD; 244 out[3] = S_BASE64PAD; 245 buffer.append(out); 246 } else if (rest == 2) { 247 int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); 248 out[0] = S_BASE64CHAR[i >> 10]; 249 out[1] = S_BASE64CHAR[(i >> 4) & 0x3f]; 250 out[2] = S_BASE64CHAR[(i << 2) & 0x3f]; 251 out[3] = S_BASE64PAD; 252 buffer.append(out); 253 } 254 } 255 256 /** Outputs base64 representation of the specified byte array to a byte stream. */ 257 public static void encode(byte[] data, int off, int len, 258 OutputStream ostream) throws IOException { 259 if (len <= 0) 260 return; 261 byte[] out = new byte[4]; 262 int rindex = off; 263 int rest = len - off; 264 while (rest >= 3) { 265 int i = ((data[rindex] & 0xff) << 16) 266 + ((data[rindex + 1] & 0xff) << 8) 267 + (data[rindex + 2] & 0xff); 268 out[0] = (byte) S_BASE64CHAR[i >> 18]; 269 out[1] = (byte) S_BASE64CHAR[(i >> 12) & 0x3f]; 270 out[2] = (byte) S_BASE64CHAR[(i >> 6) & 0x3f]; 271 out[3] = (byte) S_BASE64CHAR[i & 0x3f]; 272 ostream.write(out, 0, 4); 273 rindex += 3; 274 rest -= 3; 275 } 276 if (rest == 1) { 277 int i = data[rindex] & 0xff; 278 out[0] = (byte) S_BASE64CHAR[i >> 2]; 279 out[1] = (byte) S_BASE64CHAR[(i << 4) & 0x3f]; 280 out[2] = (byte) S_BASE64PAD; 281 out[3] = (byte) S_BASE64PAD; 282 ostream.write(out, 0, 4); 283 } else if (rest == 2) { 284 int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); 285 out[0] = (byte) S_BASE64CHAR[i >> 10]; 286 out[1] = (byte) S_BASE64CHAR[(i >> 4) & 0x3f]; 287 out[2] = (byte) S_BASE64CHAR[(i << 2) & 0x3f]; 288 out[3] = (byte) S_BASE64PAD; 289 ostream.write(out, 0, 4); 290 } 291 } 292 293 /** Outputs base64 representation of the specified byte array to a character stream. */ 294 public static void encode(byte[] data, int off, int len, Writer writer) 295 throws IOException { 296 if (len <= 0) 297 return; 298 char[] out = new char[4]; 299 int rindex = off; 300 int rest = len - off; 301 int output = 0; 302 while (rest >= 3) { 303 int i = ((data[rindex] & 0xff) << 16) 304 + ((data[rindex + 1] & 0xff) << 8) 305 + (data[rindex + 2] & 0xff); 306 out[0] = S_BASE64CHAR[i >> 18]; 307 out[1] = S_BASE64CHAR[(i >> 12) & 0x3f]; 308 out[2] = S_BASE64CHAR[(i >> 6) & 0x3f]; 309 out[3] = S_BASE64CHAR[i & 0x3f]; 310 writer.write(out, 0, 4); 311 rindex += 3; 312 rest -= 3; 313 output += 4; 314 if (output % 76 == 0) 315 writer.write("\n"); 316 } 317 if (rest == 1) { 318 int i = data[rindex] & 0xff; 319 out[0] = S_BASE64CHAR[i >> 2]; 320 out[1] = S_BASE64CHAR[(i << 4) & 0x3f]; 321 out[2] = S_BASE64PAD; 322 out[3] = S_BASE64PAD; 323 writer.write(out, 0, 4); 324 } else if (rest == 2) { 325 int i = ((data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff); 326 out[0] = S_BASE64CHAR[i >> 10]; 327 out[1] = S_BASE64CHAR[(i >> 4) & 0x3f]; 328 out[2] = S_BASE64CHAR[(i << 2) & 0x3f]; 329 out[3] = S_BASE64PAD; 330 writer.write(out, 0, 4); 331 } 332 } 333}