package eu.dnetlib.client.shared;

 

	/**
	 * @param args
	 */
	public class Base64 {
		byte[] encodeData;
		String charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

		{
			encodeData = new byte[64];
			for (int i = 0; i < 64; i++) {
				byte c = (byte) charSet.charAt(i);
				encodeData[i] = c;
			}
		}

		public Base64() {
		}

		/**
		 * base-64 encode a string
		 * 
		 * @param s
		 *            The ascii string to encode
		 * @returns The base64 encoded result
		 */

		public String encode(String s) {
			return encode(s.getBytes());
		}

		/**
		 * base-64 encode a byte array
		 * 
		 * @param src
		 *            The byte array to encode
		 * @returns The base64 encoded result
		 */

		public String encode(byte[] src) {
			return encode(src, 0, src.length);
		}

		/**
		 * base-64 encode a byte array
		 * 
		 * @param src
		 *            The byte array to encode
		 * @param start
		 *            The starting index
		 * @param len
		 *            The number of bytes
		 * @returns The base64 encoded result
		 */

		public String encode(byte[] src, int start, int length) {
			byte[] dst = new byte[(length + 2) / 3 * 4 + length / 72];
			int x = 0;
			int dstIndex = 0;
			int state = 0; // which char in pattern
			int old = 0; // previous byte
			int len = 0; // length decoded so far
			int max = length + start;
			for (int srcIndex = start; srcIndex < max; srcIndex++) {
				x = src[srcIndex];
				switch (++state) {
				case 1:
					dst[dstIndex++] = encodeData[(x >> 2) & 0x3f];
					break;
				case 2:
					dst[dstIndex++] = encodeData[((old << 4) & 0x30)
							| ((x >> 4) & 0xf)];
					break;
				case 3:
					dst[dstIndex++] = encodeData[((old << 2) & 0x3C)
							| ((x >> 6) & 0x3)];
					dst[dstIndex++] = encodeData[x & 0x3F];
					state = 0;
					break;
				}
				old = x;
				if (++len >= 72) {
					dst[dstIndex++] = (byte) '\n';
					len = 0;
				}
			}

			/*
			 * now clean up the end bytes
			 */

			switch (state) {
			case 1:
				dst[dstIndex++] = encodeData[(old << 4) & 0x30];
				dst[dstIndex++] = (byte) '=';
				dst[dstIndex++] = (byte) '=';
				break;
			case 2:
				dst[dstIndex++] = encodeData[(old << 2) & 0x3c];
				dst[dstIndex++] = (byte) '=';
				break;
			}
			return new String(dst);
		}

		/**
		 * A Base64 decoder. This implementation is slow, and doesn't handle
		 * wrapped lines. The output is undefined if there are errors in the
		 * input.
		 * 
		 * @param s
		 *            a Base64 encoded string
		 * @returns The byte array eith the decoded result
		 */

		public byte[] decode(String s) {
			int end = 0; // end state
			if (s.endsWith("=")) {
				end++;
			}
			if (s.endsWith("==")) {
				end++;
			}
			int len = (s.length() + 3) / 4 * 3 - end;
			byte[] result = new byte[len];
			int dst = 0;
			try {
				for (int src = 0; src < s.length(); src++) {
					int code = charSet.indexOf(s.charAt(src));
					if (code == -1) {
						break;
					}
					switch (src % 4) {
					case 0:
						result[dst] = (byte) (code << 2);
						break;
					case 1:
						result[dst++] |= (byte) ((code >> 4) & 0x3);
						result[dst] = (byte) (code << 4);
						break;
					case 2:
						result[dst++] |= (byte) ((code >> 2) & 0xf);
						result[dst] = (byte) (code << 6);
						break;
					case 3:
						result[dst++] |= (byte) (code & 0x3f);
						break;
					}
				}
			} catch (ArrayIndexOutOfBoundsException e) {
			}
			return result;
		}

	}

//		 
//		 public final class  Base64 {
//		      static private final int  BASELENGTH         = 255;       
//		      static private final int  LOOKUPLENGTH       = 64;
//		      static private final int  TWENTYFOURBITGROUP = 24;
//		      static private final int  EIGHTBIT           = 8;
//		      static private final int  SIXTEENBIT         = 16;
//	      static private final int  SIXBIT             = 6;
//		      static private final int  FOURBYTE           = 4;
//	      static private final int  SIGN               = -128;
//		      static private final byte PAD                = ( byte ) '=';
//		      static private final boolean fDebug          = false;
//	      static private byte [] base64Alphabet       = new byte[BASELENGTH]; 
//		      static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
//		  
//		  
//		       static {
//		 
//		           for (int i = 0; i<BASELENGTH; i++ ) {
//		              base64Alphabet[i] = -1; 
//		           }
//		           for ( int i = 'Z'; i >= 'A'; i-- ) {
//		               base64Alphabet[i] = (byte) (i-'A');
//		           }
//		          for ( int i = 'z'; i>= 'a'; i--) {
//		               base64Alphabet[i] = (byte) ( i-'a' + 26);
//		          }
//		  
//		          for ( int i = '9'; i >= '0'; i--) {
//		             base64Alphabet[i] = (byte) (i-'0' + 52);
//		         }
//		  
//		          base64Alphabet['+']  = 62; 
//		         base64Alphabet['/']  = 63;
//		  
//		         for (int i = 0; i<=25; i++ )
//		              lookUpBase64Alphabet[i] = (byte) ('A'+i );
//		 
//		         for (int i = 26,  j = 0; i<=51; i++, j++ )
//		              lookUpBase64Alphabet[i] = (byte) ('a'+ j );
//		  
//		         for (int i = 52,  j = 0; i<=61; i++, j++ )
//		             lookUpBase64Alphabet[i] = (byte) ('0' + j );
//		          lookUpBase64Alphabet[62] = (byte) '+';
//		          lookUpBase64Alphabet[63] = (byte) '/';
//		 
//	     }
//	 
//	      public static boolean isBase64( String isValidString ){
//		         return( isArrayByteBase64( isValidString.getBytes()));
//		     }
//		 
//		  
//		     public static boolean isBase64( byte octect ) {
//		         //shall we ignore white space? JEFF??
//		         return(octect == PAD || base64Alphabet[octect] != -1 ); 
//		      }
//		 
//		 
//	     public static boolean isArrayByteBase64( byte[] arrayOctect ) {
//		          int length = arrayOctect.length;
//		         if ( length == 0 )
//	             return false;
//		         for ( int i=0; i < length; i++ ) {
//	             if ( Base64.isBase64( arrayOctect[i] ) == false)
//	                 return false;
//		        }
//	         return true;
//		      }144 
		 
//		     /**
//		145      * Encodes hex octects into Base64
//		146      * 
//		147      * @param binaryData Array containing binaryData
//		148      * @return Encoded Base64 array
//		149      */
//		150     public static byte[] encode( byte[] binaryData ) {
//		151         int      lengthDataBits    = binaryData.length*EIGHTBIT;
//		152         int      fewerThan24bits   = lengthDataBits%TWENTYFOURBITGROUP; 
//		153         int      numberTriplets    = lengthDataBits/TWENTYFOURBITGROUP;
//		154         byte     encodedData[]     = null;
//		155 
//		156 
//		157         if ( fewerThan24bits != 0 ) //data not divisible by 24 bit
//		158             encodedData = new byte[ (numberTriplets + 1 )*4  ];
//		159         else // 16 or 8 bit
//		160             encodedData = new byte[ numberTriplets*4 ];
//		161 
//		162         byte k=0, l=0, b1=0,b2=0,b3=0;
//		163 
//		164         int encodedIndex = 0;
//		165         int dataIndex   = 0;
//		166         int i           = 0;
//		167         if (fDebug ) {
//		168             System.out.println("number of triplets = " + numberTriplets );
//		169         }
//		170         for ( i = 0; i<numberTriplets; i++ ) {
//		171 
//		172             dataIndex = i*3;
//		173             b1 = binaryData[dataIndex]; 
//		174             b2 = binaryData[dataIndex + 1];
//		175             b3 = binaryData[dataIndex + 2];
//		176 
//		177             if (fDebug) {
//		178                 System.out.println( "b1= " + b1 +", b2= " + b2 + ", b3= " + b3 );
//		179             }
//		180 
//		181             l  = (byte)(b2 & 0x0f);
//		182             k  = (byte)(b1 & 0x03);
//		183 
//		184             encodedIndex = i*4;
//		185             byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
//		186 
//		187             byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0); 
//		188             byte val3 = ((b3 & SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc);
//		189 
//		190             encodedData[encodedIndex]   = lookUpBase64Alphabet[ val1 ]; 
//		191             if (fDebug) {
//		192                 System.out.println( "val2 = " + val2 );
//		193                 System.out.println( "k4   = " + (k<<4));
//		194                 System.out.println( "vak  = " + (val2 | (k<<4)));
//		195             }
//		196 
//		197             encodedData[encodedIndex+1] = lookUpBase64Alphabet[ val2 | ( k<<4 )];
//		198             encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | val3 ]; 
//		199             encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ];
//		200         }
//		201 
//		202         // form integral number of 6-bit groups
//		203         dataIndex    = i*3;
//		204         encodedIndex = i*4;
//		205         if (fewerThan24bits == EIGHTBIT ) {
//		206             b1 = binaryData[dataIndex];
//		207             k = (byte) ( b1 &0x03 );
//		208             if (fDebug ) {
//		209                 System.out.println("b1=" + b1);
//		210                 System.out.println("b1<<2 = " + (b1>>2) );
//		211             }
//		212             byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
//		213             encodedData[encodedIndex]     = lookUpBase64Alphabet[ val1 ];
//		214             encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ]; 
//		215             encodedData[encodedIndex + 2] = PAD;
//		216             encodedData[encodedIndex + 3] = PAD;
//		217         } else if ( fewerThan24bits == SIXTEENBIT ) {
//		218 
//		219             b1 = binaryData[dataIndex];
//		220             b2 = binaryData[dataIndex +1 ];
//		221             l = ( byte ) ( b2 &0x0f );
//		222             k = ( byte ) ( b1 &0x03 );
//		223 
//		224             byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
//		225             byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0); 
//		226 
//		227             encodedData[encodedIndex]     = lookUpBase64Alphabet[ val1 ];
//		228             encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ val2 | ( k<<4 )];
//		229             encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ]; 
//		230             encodedData[encodedIndex + 3] = PAD;
//		231         }
//		232         return encodedData;
//		233     }
//		234 
//		235 
//		236     /**
//		237      * Decodes Base64 data into octects
//		238      * 
//		239      * @param binaryData Byte array containing Base64 data
//		240      * @return Array containind decoded data.
//		241      */
//		242     public static byte[] decode( byte[] base64Data ) {
//		243         int      numberQuadruple    = base64Data.length/FOURBYTE;
//		244         byte     decodedData[]      = null;
//		245         byte     b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0;
//		246 
//		247         // Throw away anything not in base64Data
//		248         // Adjust size
//		249 
//		250         int encodedIndex = 0;
//		251         int dataIndex    = 0;
//		252         decodedData      = new byte[ numberQuadruple*3 + 1 ];
//		253 
//		254         for (int i = 0; i<numberQuadruple; i++ ) {
//		255             dataIndex = i*4;
//		256             marker0   = base64Data[dataIndex +2]; 
//		257             marker1   = base64Data[dataIndex +3]; 
//		258 
//		259             b1 = base64Alphabet[base64Data[dataIndex]]; 
//		260             b2 = base64Alphabet[base64Data[dataIndex +1]];
//		261 
//		262             if ( marker0 != PAD && marker1 != PAD ) {     //No PAD e.g 3cQl
//		263                 b3 = base64Alphabet[ marker0 ];
//		264                 b4 = base64Alphabet[ marker1 ];
//		265 
//		266                 decodedData[encodedIndex]   = (byte)(  b1 <<2 | b2>>4 ) ;
//		267                 decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
//		268                 decodedData[encodedIndex+2] = (byte)( b3<<6 | b4 ); 
//		269             } else if ( marker0 == PAD ) {               //Two PAD e.g. 3c[Pad][Pad]
//		270                 decodedData[encodedIndex]   = (byte)(  b1 <<2 | b2>>4 ) ; 
//		271                 decodedData[encodedIndex+1] = (byte)((b2 & 0xf)<<4 );  
//		272                 decodedData[encodedIndex+2] = (byte) 0; 
//		273             } else if ( marker1 == PAD ) {              //One PAD e.g. 3cQ[Pad]
//		274                 b3 = base64Alphabet[ marker0 ];
//		275 
//		276                 decodedData[encodedIndex]   = (byte)(  b1 <<2 | b2>>4 );
//		277                 decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
//		278                 decodedData[encodedIndex+2] = (byte)( b3<<6); 
//		279             }
//		280             encodedIndex += 3;
//		281         }
//		282         return decodedData;
//		283 
//		284     }
//		285 }                 
