| /* |
| * Copyright 2009 Alin Dreghiciu. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| * implied. |
| * |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.zest.api.util; |
| |
| /** |
| * Base64Encoder. |
| */ |
| public final class Base64Encoder |
| { |
| |
| /** |
| * Utility class. ment to be used via static methods. |
| */ |
| private Base64Encoder() |
| { |
| // utility class |
| } |
| |
| /** |
| * Encodes a String into a base 64 String. The resulting encoding is chunked at 76 bytes. |
| * |
| * @param s String to encode. |
| * |
| * @return encoded string. |
| */ |
| public static String encode( String s, boolean includePadding ) |
| { |
| byte[] sBytes = s.getBytes(); |
| sBytes = encode( sBytes, includePadding ); |
| s = new String( sBytes ); |
| return s; |
| } |
| |
| /** |
| * Decodes a base 64 String into a String. |
| * |
| * @param s String to decode. |
| * |
| * @return encoded string. |
| * |
| * @throws java.lang.IllegalArgumentException |
| * _ If the given byte array was not valid base64 encoding. |
| */ |
| public static String decode( String s ) |
| throws IllegalArgumentException |
| { |
| s = s.replaceAll( "\n", "" ); |
| s = s.replaceAll( "\r", "" ); |
| byte[] sBytes = s.getBytes(); |
| sBytes = decode( sBytes ); |
| s = new String( sBytes ); |
| return s; |
| } |
| |
| private static final byte[] ALPHASET = |
| "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".getBytes(); |
| |
| private static final int I6O2 = 255 - 3; |
| private static final int O6I2 = 3; |
| private static final int I4O4 = 255 - 15; |
| private static final int O4I4 = 15; |
| private static final int I2O6 = 255 - 63; |
| private static final int O2I6 = 63; |
| |
| /** |
| * Encodes a byte array into a base 64 byte array. |
| * |
| * @param dData byte array to encode. |
| * |
| * @return encoded byte array. |
| */ |
| public static byte[] encode( byte[] dData, boolean includePadding ) |
| { |
| if( dData == null ) |
| { |
| throw new IllegalArgumentException( "Cannot encode null" ); |
| } |
| byte[] eData = new byte[ ( ( dData.length + 2 ) / 3 ) * 4 ]; |
| |
| int eIndex = 0; |
| for( int i = 0; i < dData.length; i += 3 ) |
| { |
| int d1; |
| int d2 = 0; |
| int d3 = 0; |
| int e1; |
| int e2; |
| int e3; |
| int e4; |
| int pad = 0; |
| |
| d1 = dData[ i ]; |
| if( ( i + 1 ) < dData.length ) |
| { |
| d2 = dData[ i + 1 ]; |
| if( ( i + 2 ) < dData.length ) |
| { |
| d3 = dData[ i + 2 ]; |
| } |
| else |
| { |
| pad = 1; |
| } |
| } |
| else |
| { |
| pad = 2; |
| } |
| |
| e1 = ALPHASET[ ( d1 & I6O2 ) >> 2 ]; |
| e2 = ALPHASET[ ( d1 & O6I2 ) << 4 | ( d2 & I4O4 ) >> 4 ]; |
| e3 = ALPHASET[ ( d2 & O4I4 ) << 2 | ( d3 & I2O6 ) >> 6 ]; |
| e4 = ALPHASET[ ( d3 & O2I6 ) ]; |
| |
| eData[ eIndex++ ] = (byte) e1; |
| eData[ eIndex++ ] = (byte) e2; |
| eData[ eIndex++ ] = ( pad < 2 ) ? (byte) e3 : (byte) '='; |
| eData[ eIndex++ ] = ( pad < 1 ) ? (byte) e4 : (byte) '='; |
| |
| if( pad > 0 && !includePadding ) |
| { |
| byte[] neweData = new byte[ eData.length - pad ]; |
| System.arraycopy( eData, 0, neweData, 0, eIndex - pad ); |
| eData = neweData; |
| } |
| } |
| |
| return eData; |
| } |
| |
| private final static int[] CODES = new int[ 256 ]; |
| |
| static |
| { |
| for( int i = 0; i < CODES.length; i++ ) |
| { |
| CODES[ i ] = 64; |
| } |
| for( int i = 0; i < ALPHASET.length; i++ ) |
| { |
| CODES[ ALPHASET[ i ] ] = i; |
| } |
| } |
| |
| /** |
| * Decodes a base64 byte array into a byte array. |
| * <p> |
| * |
| * @param eData byte array to decode. |
| * |
| * @return decoded byte array. |
| * |
| * @throws java.lang.IllegalArgumentException |
| * thrown if the given byte array was not valid com.sun.syndication.io.impl.Base64 encoding. |
| */ |
| public static byte[] decode( byte[] eData ) |
| { |
| if( eData == null ) |
| { |
| throw new IllegalArgumentException( "Cannot decode null" ); |
| } |
| byte[] cleanEData = eData.clone(); |
| int cleanELength = 0; |
| for( byte anEData : eData ) |
| { |
| if( anEData < 256 && CODES[ anEData ] < 64 ) |
| { |
| cleanEData[ cleanELength++ ] = anEData; |
| } |
| } |
| |
| int dLength = ( cleanELength / 4 ) * 3; |
| switch( cleanELength % 4 ) |
| { |
| case 3: |
| dLength += 2; |
| break; |
| case 2: |
| dLength++; |
| break; |
| } |
| |
| byte[] dData = new byte[ dLength ]; |
| int dIndex = 0; |
| for( int i = 0; i < eData.length; i += 4 ) |
| { |
| if( ( i + 3 ) > eData.length ) |
| { |
| throw new IllegalArgumentException( |
| "byte array is not a valid base64 encoding" |
| ); |
| } |
| int e1 = CODES[ cleanEData[ i ] ]; |
| int e2 = CODES[ cleanEData[ i + 1 ] ]; |
| int e3 = CODES[ cleanEData[ i + 2 ] ]; |
| int e4 = CODES[ cleanEData[ i + 3 ] ]; |
| dData[ dIndex++ ] = (byte) ( ( e1 << 2 ) | ( e2 >> 4 ) ); |
| if( dIndex < dData.length ) |
| { |
| dData[ dIndex++ ] = (byte) ( ( e2 << 4 ) | ( e3 >> 2 ) ); |
| } |
| if( dIndex < dData.length ) |
| { |
| dData[ dIndex++ ] = (byte) ( ( e3 << 6 ) | ( e4 ) ); |
| } |
| } |
| return dData; |
| } |
| } |