com.adobe.xfa.ut.Base64 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*
* ADOBE CONFIDENTIAL
*
* Copyright 2005 Adobe Systems Incorporated All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of
* Adobe Systems Incorporated and its suppliers, if any. The intellectual and
* technical concepts contained herein are proprietary to Adobe Systems
* Incorporated and its suppliers and may be covered by U.S. and Foreign
* Patents, patents in process, and are protected by trade secret or copyright
* law. Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained from
* Adobe Systems Incorporated.
*/
package com.adobe.xfa.ut;
/**
* Utility class for Base64 encoding and decoding
*
* @exclude from published api.
*/
public final class Base64 {
private static final char cBase64Pad = '=';
// 127 is the "invalid" value
private static final byte[] szBase64Decoding = {
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 62, 127, 127, 127, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, 127, 127, 127, 127,
127, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 127, 127, 127, 127, 127,
127, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 127, 127, 127, 127, 127,
};
private static final String szBase64Encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// This method has been optimized for decoding chars
// It will not use the template implementation
private static void decode(byte[] pData, String pEncoded) {
// BaseBase64Decode (pData, nResultSize, pEncoded, nInputLength,
// pnNumUnDecodedChars);
int nCount = 0;
int nAccumulator = 0;
int nBits = 0;
int resultPos = 0;
// Check for an empty string
if (pEncoded.length() == 0)
return;
while (nCount < pEncoded.length()) {
int iChar = pEncoded.charAt(nCount);
// Check for the end of the base 64 encoded data
if (iChar == '=')
break;
// ignore new lines and white space
// '\n', '\r', ' ', '\t'
if (iChar < 33
&& (iChar == '\n' || iChar == '\r' || iChar == ' '
|| iChar == '\t')) {
nCount++;
continue;
}
// wait to do the assignment on nDecodedChar until iChar is checked
// to be within the range of the szBase64Decoding table
byte nDecodedChar;
if (iChar > 127 || szBase64Decoding[iChar] > 63)
throw new ExFull(ResId.ILLEGAL_BASE64_ENCODING);
nDecodedChar = szBase64Decoding[iChar];
nAccumulator <<= 6;
nAccumulator |= nDecodedChar;
nBits += 6;
if (nBits >= 8) {
pData[resultPos++] = (byte) (nAccumulator >> (nBits - 8));
nBits -= 8;
}
nCount++;
}
// if the "extra" bits aren't 0, the data was wrong
if (nBits != 0
&& (nAccumulator & ((~0 << nBits) ^ ~0)) != 0)
throw new ExFull(ResId.ILLEGAL_BASE64_ENCODING);
}
// // Enables encoding a large base64 data block by calling the method
// // several times, will not add padding characters until the last part.
// void Base64EncodePart(byte[] pEncoded,
// byte[] pData,
// char[] pcRemaining,
// int& nNumRemaining,
// int nStartIndex,
// long& nAccumulator,
// int& nChars,
// int& nEncodedLength,
// int nMaxEncodeLength,
// int nDataSize,
// boolean bLastPart,
// boolean bBreakLines)
// {
// int nBits = 0;
// int nCount;
// int nTotal = 0;
//
// // return if we have no data
// if (nDataSize == 0 || pData == null)
// {
// *pEncoded = 0;
// nNumRemaining = 0;
// nEncodedLength = 0;
// return;
// }
//
// // reset the number of buffered characters
// nNumRemaining = 0;
//
// for (nCount = 0; nCount < nDataSize; nCount++)
// {
// // add a line feed every 76 characters (as per the base64 specification
// // in the MIME standard)
// if (bBreakLines && nChars % 76 == 0 && nChars != 0)
// {
// if (nTotal < nMaxEncodeLength)
// {
// pEncoded[nStartIndex+nTotal] = '\n';
// nTotal++;
// }
// else
// pcRemaining[nNumRemaining++] = '\n';
// }
//
// // collect another character
// nAccumulator <<= 8;
// // thought about just casting to unsigned char * instead of to int and
// then masking,
// // but wasn't sure if that was portable
// nAccumulator |= (int)((char *)pData)[nCount] & 0xffl;
// nBits += 8;
//
// // encode all the 6-bit groups we have
// while (nBits >= 6)
// {
// if (nTotal < nMaxEncodeLength)
// {
// pEncoded[nStartIndex+nTotal] = szBase64Encoding [(nAccumulator >> (nBits
// - 6)) & 0x3f];
// nTotal++;
// }
// else
// pcRemaining[nNumRemaining++] = szBase64Encoding [(nAccumulator >> (nBits
// - 6)) & 0x3f];
//
// nChars++;
// nBits -= 6;
// }
// }
//
// if (nBits != 0 && bLastPart)
// {
// pEncoded[nStartIndex+nTotal] = szBase64Encoding [(nAccumulator << (6 -
// nBits)) & 0x3f];
// nTotal++;
// pEncoded[nStartIndex+nTotal] = cBase64Pad; // we need at least one pad
// character
// nTotal++;
// if (nDataSize % 3 == 1)
// {
// pEncoded[nStartIndex+nTotal] = cBase64Pad; // in this case we need an
// extra pad character
// nTotal++;
// }
// }
//
// nEncodedLength = nStartIndex+nTotal;
// }
public static byte[] decode(String sEncoded) {
int nBufferLength = decodeLength(sEncoded.length());
byte[] szResult = new byte[nBufferLength];
decode(szResult, sEncoded);
return szResult;
}
private static int decodeLength(int nLength) {
// the length will always be an exact multiple of
// four, after whitespace is ignored; therefore the
// truncation here is not a problem.
// (OH YEAH!??? Watson 2335637 says otherwise.
// Allow space for the truncation by adding 3 first.
return ((nLength+3) / 4) * 3;
}
public static String encode(byte[] pData, boolean bBreakLines/* = true */) {
String sResult = "";
if (pData != null && pData.length != 0) {
char[] pEncoded = new char[encodeLength(pData.length, bBreakLines)];
encode(pEncoded, pData, bBreakLines);
sResult = new String(pEncoded);
}
return sResult;
}
//
// implement using template to ensure that no new memory needs to
// be allocated (the encodings may be passwords, in which case
// the memory needs to be secure)
//
public static void encode(char[] pEncoded, byte[] pData, boolean bBreakLines) {
int nAccumulator = 0;
int nBits = 0;
int nCount;
int nChars = 0;
int nTotal = 0;
// short circuit if we have no data
if (pData == null || pData.length == 0) {
pEncoded[0] = 0;
return;
}
for (nCount = 0; nCount < pData.length; nCount++) {
// add a line feed every 76 characters (as per the base64
// specification
// in the MIME standard)
if (bBreakLines && nChars % 76 == 0 && nChars != 0)
pEncoded[nTotal++] = '\n';
// collect another character
nAccumulator <<= 8;
// thought about just casting to unsigned char * instead of to int
// and then masking,
// but wasn't sure if that was portable
nAccumulator |= (int) pData[nCount] & 0xffl;
nBits += 8;
// encode all the 6-bit groups we have
while (nBits >= 6) {
pEncoded[nTotal++] = szBase64Encoding
.charAt((nAccumulator >> (nBits - 6)) & 0x3f);
nChars++;
nBits -= 6;
}
}
if (nBits != 0) {
pEncoded[nTotal++] = szBase64Encoding
.charAt((nAccumulator << (6 - nBits)) & 0x3f);
pEncoded[nTotal++] = cBase64Pad; // we need at least one pad
// character
if (pData.length % 3 == 1)
pEncoded[nTotal++] = cBase64Pad; // in this case we need an
// extra pad character
}
}
private static int encodeLength(int nSize, boolean bBreakLines) {
if (nSize == 0)
return 0;
int nResult = (nSize + 2) / 3 * 4;
if (bBreakLines)
nResult += (nResult - 1) / 76;
return nResult;
}
}