WindowsXP-SP1/ds/adsi/xml/base64.cxx

192 lines
5.7 KiB
C++

//----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: base64.cxx
//
// Contents: Contains the implementation of base64 encoding.
//
//----------------------------------------------------------------------------
#include <ctype.h>
#include "cadsxml.hxx"
#define NL_STR "\r\n"
#define NL_STR_LEN 2
#define OCTETS_PER_GROUP 3
#define SEXTETS_PER_GROUP 4
#define BASE64_PAD_CHAR '='
#define BASE64_PAD_INDEX 64
/* NOTE: the pad character base64Alphabet[BASE64_PAD_INDEX] doesn't */
/* really belong the strict definition of the Base64 character set */
static
char base64Alphabet[65] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '='
};
//---------------------------------------------------------------------------
// Function: encodeGroup
//
// Synopsis: Performs base64 encoding of a group of 3 bytes.
//
// Arguments:
//
// inBufPtr Pointer to data to encode
// encodeBufPtr Encoded data
// inBufLen Number of bytes in inBufPtr
//
// Returns: Number of encoded sextets
//
// Modifies: encodeBufPtr to store the encoded data.
//
//--------------------------------------------------------------------------
static int encodeGroup (
char *inBufPtr, /* input buffer to encode (3 8-bit octets) */
char *encodeBufPtr, /* encode buffer (4 6-bit sextets) */
int inBufLen )
{
int i;
unsigned char octet;
if (inBufLen > OCTETS_PER_GROUP)
return(0);
/* perform base64 encoding (convert 3 8-bit groups to 4 6-bit groups) */
memset(encodeBufPtr, 0, SEXTETS_PER_GROUP);
for (i=0; i<inBufLen; i++) {
octet = *(inBufPtr + i);
switch (i) {
case 0:
*encodeBufPtr = (char)(octet >> 2);
*(encodeBufPtr+1) |= (char)((octet & 0x3) << 4);
break;
case 1:
*(encodeBufPtr+1) |= (char)(octet >> 4);
*(encodeBufPtr+2) |= (char)((octet & 0xf) << 2);
break;
case 2:
*(encodeBufPtr+2) |= (char)(octet >> 6);
*(encodeBufPtr+3) |= (char)(octet & 0x3f);
break;
}
}
/* perform padding for incomplete octet groups */
switch (inBufLen) {
case 1:
*(encodeBufPtr+2) = BASE64_PAD_INDEX;
/* the missing break is intentional! */
case 2:
*(encodeBufPtr+3) = BASE64_PAD_INDEX;
break;
default:
break;
}
/* translate all base64 codes into characters from the base64 alphabet */
for (i=0; i<SEXTETS_PER_GROUP; i++)
*(encodeBufPtr+i) = base64Alphabet[ *(encodeBufPtr+i) ];
return(SEXTETS_PER_GROUP); /* # of encoded sextets (incldg padding) */
}
//--------------------------------------------------------------------------
// Function: encodeBase64Buffer
//
// Synopsis: Encodes a data buffer using the "Base64" method.
//
// Arguments:
//
// inBufPtr points to input data
// inBytesPtr points to number of bytes in inBufPtr
// outBufPtr points to output area for encoded data
// outBytesPtr points to size of outBufPtr
// outLineLen number of base64 characters to output per
// line (each line is <CR><LF> terminated)
//
// Returns : 0 if successful, -1 otherwise.
//
// Modifies: *inBytesPtr to return the number of bytes encoded.
// *outBytesPtr to return number of bytes placed in outBufPtr.
// outBufPtr returns the encoded data.
//
//--------------------------------------------------------------------------
int encodeBase64Buffer (
char *inBufPtr,
int *inBytesPtr,
WCHAR *outBufPtr,
int *outBytesPtr,
int outLineLen
)
{
int i, ret, bytesToEncode, outBufSize, startOffset, encodeLen;
int octetCount, lineCount, outOfSpace;
char inBuf[OCTETS_PER_GROUP], encodeBuf[SEXTETS_PER_GROUP+NL_STR_LEN];
char *ptr;
bytesToEncode = *inBytesPtr;
outBufSize = *outBytesPtr;
*inBytesPtr = 0;
*outBytesPtr = 0;
if (bytesToEncode <= 0 || outBufSize <= 0)
return(-1);
startOffset = -1;
octetCount = lineCount = outOfSpace = 0;
for (i=0; i < bytesToEncode && !outOfSpace; i++) {
ptr = inBufPtr + i;
if (startOffset < 0)
startOffset = i;
inBuf[octetCount++] = *ptr;
/* encode the octet group if sufficient octets have been accumulated */
/* or if we're on the last byte */
if (octetCount == OCTETS_PER_GROUP
|| (i == bytesToEncode-1)) {
/* encode the input octet group into an sextet group */
encodeLen = encodeGroup(inBuf, encodeBuf, octetCount);
lineCount += encodeLen;
if (lineCount >= outLineLen) {
memcpy(&encodeBuf[encodeLen], NL_STR, NL_STR_LEN);
encodeLen += NL_STR_LEN;
lineCount = 0;
}
if (*outBytesPtr + encodeLen > outBufSize)
outOfSpace = 1;
else {
/* write decoded octets to output buffer */
ret = mbstowcs(outBufPtr + *outBytesPtr, encodeBuf, encodeLen);
*outBytesPtr += encodeLen;
*inBytesPtr += i - startOffset + 1;
startOffset = -1;
octetCount = 0;
}
}
}
// Null terminate output
if(*outBytesPtr < outBufSize) {
*(outBufPtr + *outBytesPtr) = L'\0';
(*outBytesPtr)++;
}
return(0);
}