Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

239 lines
6.0 KiB

//+----------------------------------------------------------------------------
// File: mime64.cxx
//
// Synopsis:
//
//-----------------------------------------------------------------------------
// Includes -------------------------------------------------------------------
#include <core.hxx>
// Constants ------------------------------------------------------------------
const LARGE_INTEGER LIB_ZERO = { 0, 0 };
const ULONG BUFFER_SIZE = 256;
const UCHAR INVALID_CHAR = (UCHAR)-2;
const UCHAR IGNORE_CHAR = (UCHAR)-1;
const UCHAR CH_TERMINATION = '=';
const char achAlpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
// Globals --------------------------------------------------------------------
UCHAR g_anBinary[256];
// Prototypes -----------------------------------------------------------------
inline ULONG BinaryFromASCII(UCHAR ch) { return g_anBinary[ch]; }
//+----------------------------------------------------------------------------
// Function: ProcessAttachMIME64
//
// Synopsis:
//
//-----------------------------------------------------------------------------
HRESULT
ProcessAttachMIME64()
{
UCHAR ubin;
UCHAR ch;
int i;
// BUGBUG: Hard code this table
for (i=0; i < ARRAY_SIZE(g_anBinary); i++)
{
ch = (UCHAR)i;
switch (ch)
{
case ' ' :
case '\t':
case '\n':
case '\r':
ubin = IGNORE_CHAR;
break;
default:
if ((ch >= 'A') && (ch <= 'Z'))
ubin = (UCHAR)(ch - 'A');
else if ((ch >= 'a') && (ch <= 'z'))
ubin = (UCHAR)(26 + (ch - 'a'));
else if ((ch >= '0') && (ch <= '9'))
ubin = (UCHAR)(52 + (ch - '0'));
else
ubin = INVALID_CHAR;
break;
case '+':
ubin = 62;
break;
case '/':
ubin = 63;
break;
}
g_anBinary[i] = ubin;
}
return S_OK;
}
//+----------------------------------------------------------------------------
// Function: EncodeMIME64
//
// Synopsis:
//
//-----------------------------------------------------------------------------
HRESULT
EncodeMIME64(
BYTE * pbSrc,
UINT cbSrc,
IStream * pstmDest,
ULONG * pcbWritten)
{
UCHAR achOut[(2 * sizeof(UCHAR)) + CB_NEWLINE];
ULONG ichOut = 0;
ULONG cbWritten;
ULONG cbTotalWritten;
ULONG bAccum = 0;
ULONG cShift = 0;
HRESULT hr = S_OK;
Assert(pbSrc);
Assert(pstmDest);
if (!pcbWritten)
{
pcbWritten = &cbTotalWritten;
}
// Convert the source string, 6-bits at a time, to ASCII characters
while (cbSrc)
{
bAccum <<= 8;
cShift += 8;
bAccum |= *pbSrc++;
cbSrc--;
while (cShift >= 6)
{
cShift -= 6;
hr = pstmDest->Write(&achAlpha[(bAccum >> cShift) & 0x3FL], 1, &cbWritten);
*pcbWritten += cbWritten;
if (hr)
goto Cleanup;
}
}
// If there are bits not yet written, pad with zeros and write the resulting character
if (cShift)
{
bAccum <<= 6 - cShift;
achOut[ichOut++] = achAlpha[(bAccum >> cShift) & 0x3FL];
}
// Add a termination character and newline
achOut[ichOut++] = CH_TERMINATION;
::memcpy(achOut+ichOut, SZ_NEWLINE, CB_NEWLINE);
ichOut += CB_NEWLINE;
hr = pstmDest->Write(achOut, ichOut, &cbWritten);
*pcbWritten += cbWritten;
if (hr)
goto Cleanup;
Cleanup:
return hr;
}
//+----------------------------------------------------------------------------
// Function: DecodeMIME64
//
// Synopsis:
//
//-----------------------------------------------------------------------------
HRESULT
DecodeMIME64(
IStream * pstmSrc,
IStream * pstmDest,
ULONG * pcbWritten)
{
UCHAR ch;
UCHAR achOut[BUFFER_SIZE];
ULONG ichOut = 0;
ULONG cbRead;
ULONG cbWritten;
ULONG cbTotalWritten = 0;
ULONG bAccum = 0;
ULONG cShift = 0;
ULONG bValue;
HRESULT hr;
if (!pcbWritten)
{
pcbWritten = &cbTotalWritten;
}
// As long as characters remain, convert them to binary
// (This loop skips "whitespace" and stops when it encounters an out-of-range value)
for (;;)
{
hr = pstmSrc->Read(&ch, sizeof(ch), &cbRead);
if (hr)
goto Cleanup;
// Stop when no more characters remain
if (!cbRead)
break;
bValue = BinaryFromASCII(ch);
// Convert known characters back to binary
if (bValue < 64)
{
bAccum <<= 6;
cShift += 6;
bAccum |= bValue;
if (cShift >= 8)
{
cShift -= 8;
achOut[ichOut++] = (UCHAR)((bAccum >> cShift) & 0xFF);
if (ichOut >= ARRAY_SIZE(achOut))
{
hr = pstmDest->Write(achOut, ichOut, &cbWritten);
*pcbWritten += cbWritten;
if (hr)
goto Cleanup;
ichOut = 0;
}
}
}
// Skip "whitespace"
else if (bValue == IGNORE_CHAR)
;
// Stop if anything else is encountered
else
break;
}
// If characters remain to be written, write them now
if (ichOut)
{
hr = pstmDest->Write(achOut, ichOut, &cbWritten);
*pcbWritten += cbWritten;
if (hr)
goto Cleanup;
}
Cleanup:
return hr;
}