192 lines
5.5 KiB
C++
192 lines
5.5 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);
|
|
}
|