namespace com.hitrust.trustpay.client
|
|
{
|
|
using System;
|
|
using System.Text;
|
|
|
|
public class Base64
|
|
{
|
|
private const int EIGHT_BIT_MASK = 0xff;
|
|
private const int LOWER_CASE_A_VALUE = 0x1a;
|
|
private int mIndex = 0;
|
|
private string mString;
|
|
private const int PLUS_VALUE = 0x3e;
|
|
private const int SIX_BIT_MASK = 0x3f;
|
|
private const int SLASH_VALUE = 0x3f;
|
|
private const int ZERO_VALUE = 0x34;
|
|
|
|
private int convertUnsignedByteToInt(byte b)
|
|
{
|
|
if (b >= 0)
|
|
{
|
|
return b;
|
|
}
|
|
return (0x100 + b);
|
|
}
|
|
|
|
public byte[] decode(string data)
|
|
{
|
|
this.mString = data;
|
|
this.mIndex = 0;
|
|
int mUsefulLength = 0;
|
|
int length = this.mString.Length;
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
if (this.isUsefulChar(this.mString[i]))
|
|
{
|
|
mUsefulLength++;
|
|
}
|
|
}
|
|
int byteArrayLength = (mUsefulLength * 3) / 4;
|
|
byte[] result = new byte[byteArrayLength];
|
|
int byteTriplet = 0;
|
|
int byteIndex = 0;
|
|
while ((byteIndex + 2) < byteArrayLength)
|
|
{
|
|
byteTriplet = this.mapCharToInt(this.NextUsefulChar) << 6;
|
|
byteTriplet |= this.mapCharToInt(this.NextUsefulChar);
|
|
byteTriplet = byteTriplet << 6;
|
|
byteTriplet |= this.mapCharToInt(this.NextUsefulChar);
|
|
byteTriplet = byteTriplet << 6;
|
|
byteTriplet |= this.mapCharToInt(this.NextUsefulChar);
|
|
result[byteIndex + 2] = (byte) (byteTriplet & 0xff);
|
|
byteTriplet = byteTriplet >> 8;
|
|
result[byteIndex + 1] = (byte) (byteTriplet & 0xff);
|
|
byteTriplet = byteTriplet >> 8;
|
|
result[byteIndex] = (byte) (byteTriplet & 0xff);
|
|
byteIndex += 3;
|
|
}
|
|
if (byteIndex == (byteArrayLength - 1))
|
|
{
|
|
byteTriplet = this.mapCharToInt(this.NextUsefulChar) << 6;
|
|
byteTriplet |= this.mapCharToInt(this.NextUsefulChar);
|
|
byteTriplet = byteTriplet >> 4;
|
|
result[byteIndex] = (byte) (byteTriplet & 0xff);
|
|
}
|
|
if (byteIndex == (byteArrayLength - 2))
|
|
{
|
|
byteTriplet = this.mapCharToInt(this.NextUsefulChar) << 6;
|
|
byteTriplet |= this.mapCharToInt(this.NextUsefulChar);
|
|
byteTriplet = byteTriplet << 6;
|
|
byteTriplet |= this.mapCharToInt(this.NextUsefulChar);
|
|
byteTriplet = byteTriplet >> 2;
|
|
result[byteIndex + 1] = (byte) (byteTriplet & 0xff);
|
|
byteTriplet = byteTriplet >> 8;
|
|
result[byteIndex] = (byte) (byteTriplet & 0xff);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public string encode(byte[] data)
|
|
{
|
|
byte b3;
|
|
byte b2;
|
|
byte b1;
|
|
int charCount = ((data.Length * 4) / 3) + 4;
|
|
StringBuilder result = new StringBuilder((charCount * 0x4d) / 0x4c);
|
|
int byteArrayLength = data.Length;
|
|
int byteArrayIndex = 0;
|
|
int byteTriplet = 0;
|
|
while (byteArrayIndex < (byteArrayLength - 2))
|
|
{
|
|
byteTriplet = this.convertUnsignedByteToInt(data[byteArrayIndex++]) << 8;
|
|
byteTriplet |= this.convertUnsignedByteToInt(data[byteArrayIndex++]);
|
|
byteTriplet = byteTriplet << 8;
|
|
byteTriplet |= this.convertUnsignedByteToInt(data[byteArrayIndex++]);
|
|
byte b4 = (byte) (0x3f & byteTriplet);
|
|
byteTriplet = byteTriplet >> 6;
|
|
b3 = (byte) (0x3f & byteTriplet);
|
|
byteTriplet = byteTriplet >> 6;
|
|
b2 = (byte) (0x3f & byteTriplet);
|
|
byteTriplet = byteTriplet >> 6;
|
|
b1 = (byte) (0x3f & byteTriplet);
|
|
result.Append(this.mapByteToChar(b1));
|
|
result.Append(this.mapByteToChar(b2));
|
|
result.Append(this.mapByteToChar(b3));
|
|
result.Append(this.mapByteToChar(b4));
|
|
}
|
|
if (byteArrayIndex == (byteArrayLength - 1))
|
|
{
|
|
byteTriplet = this.convertUnsignedByteToInt(data[byteArrayIndex++]) << 4;
|
|
b2 = (byte) (0x3f & byteTriplet);
|
|
byteTriplet = byteTriplet >> 6;
|
|
b1 = (byte) (0x3f & byteTriplet);
|
|
result.Append(this.mapByteToChar(b1));
|
|
result.Append(this.mapByteToChar(b2));
|
|
result.Append("==");
|
|
}
|
|
if (byteArrayIndex == (byteArrayLength - 2))
|
|
{
|
|
byteTriplet = this.convertUnsignedByteToInt(data[byteArrayIndex++]) << 8;
|
|
byteTriplet |= this.convertUnsignedByteToInt(data[byteArrayIndex++]);
|
|
byteTriplet = byteTriplet << 2;
|
|
b3 = (byte) (0x3f & byteTriplet);
|
|
byteTriplet = byteTriplet >> 6;
|
|
b2 = (byte) (0x3f & byteTriplet);
|
|
byteTriplet = byteTriplet >> 6;
|
|
b1 = (byte) (0x3f & byteTriplet);
|
|
result.Append(this.mapByteToChar(b1));
|
|
result.Append(this.mapByteToChar(b2));
|
|
result.Append(this.mapByteToChar(b3));
|
|
result.Append("=");
|
|
}
|
|
return result.ToString();
|
|
}
|
|
|
|
private bool isUsefulChar(char c)
|
|
{
|
|
return (((((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) || (((c >= '0') && (c <= '9')) || (c == '+'))) || (c == '/'));
|
|
}
|
|
|
|
private char mapByteToChar(byte b)
|
|
{
|
|
if (b < 0x1a)
|
|
{
|
|
return (char) (0x41 + b);
|
|
}
|
|
if (b < 0x34)
|
|
{
|
|
return (char) (0x61 + (b - 0x1a));
|
|
}
|
|
if (b < 0x3e)
|
|
{
|
|
return (char) (0x30 + (b - 0x34));
|
|
}
|
|
if (b == 0x3e)
|
|
{
|
|
return '+';
|
|
}
|
|
if (b != 0x3f)
|
|
{
|
|
throw new ArgumentException("Byte " + b + " is not a valid Base64 value");
|
|
}
|
|
return '/';
|
|
}
|
|
|
|
private int mapCharToInt(char c)
|
|
{
|
|
if ((c >= 'A') && (c <= 'Z'))
|
|
{
|
|
return (c - 'A');
|
|
}
|
|
if ((c >= 'a') && (c <= 'z'))
|
|
{
|
|
return ((c - 'a') + 0x1a);
|
|
}
|
|
if ((c >= '0') && (c <= '9'))
|
|
{
|
|
return ((c - '0') + 0x34);
|
|
}
|
|
if (c == '+')
|
|
{
|
|
return 0x3e;
|
|
}
|
|
if (c != '/')
|
|
{
|
|
throw new ArgumentException(c + " is not a valid Base64 character.");
|
|
}
|
|
return 0x3f;
|
|
}
|
|
|
|
private char NextUsefulChar
|
|
{
|
|
get
|
|
{
|
|
char result = '_';
|
|
while (!this.isUsefulChar(result))
|
|
{
|
|
result = this.mString[this.mIndex++];
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|