windows-nt/Source/XPSP1/NT/shell/ext/webcheck/encodeqp.cpp
2020-09-26 16:20:57 +08:00

197 lines
5.5 KiB
C++

// --------------------------------------------------------------------------------
// EncodeQP.cpp
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
// Steven J. Bailey
//
// Stolen from Athena's source base by JulianJ, January 21st, 1997
//
// --------------------------------------------------------------------------------
#include "private.h"
//
// Porting macros so the code can be copied without changes
//
#define MIMEOLEAPI
#define AssertSz ASSERT_MSG
#define TrapError(hr) ((EVAL(SUCCEEDED(hr))), (hr))
#define CCHMAX_ENCODE_BUFFER 4096
#define CHECKHR(hrExp) \
if (FAILED (hrExp)) { \
ASSERT_MSG(SUCCEEDED(hr), "%x", (hr)); \
goto exit; \
} else
// --------------------------------------------------------------------------------
// QP Encoder
// --------------------------------------------------------------------------------
static char rgchHex[] = "0123456789ABCDEF";
#define ENCODEQPBUF 4096
#define CCHMAX_QPLINE 72
// --------------------------------------------------------------------------------
// MimeOleEncodeStreamQP
// --------------------------------------------------------------------------------
MIMEOLEAPI HRESULT MimeOleEncodeStreamQP(IStream *pstmIn, IStream *pstmOut)
{
// Locals
HRESULT hr=S_OK;
BOOL fSeenCR=FALSE,
fEOLN=FALSE;
CHAR szBuffer[CCHMAX_ENCODE_BUFFER];
ULONG cbRead=0,
cbCurr=1,
cbAttLast=0,
cbBffLast=0,
cbBuffer=0;
UCHAR chThis=0,
chPrev=0,
buf[ENCODEQPBUF];
// check params
if (NULL == pstmIn || NULL == pstmOut)
return TrapError(E_INVALIDARG);
// Read from pstmIn and encode into pstmOut
while (1)
{
// Reads one buffer full from the attachment
if (cbCurr >= cbRead)
{
// Moves buffer from the last white space to front
cbCurr = 0;
while (cbAttLast < cbRead)
buf[cbCurr++] = buf[cbAttLast++];
// RAID-33342 - Reset cbAttLast - buff[0] is now equal to cbAttLast !!!
cbAttLast = 0;
// Read into buf
CHECKHR(hr = pstmIn->Read(buf+cbCurr, ENCODEQPBUF-cbCurr, &cbRead));
// No more ?
if (cbRead == 0)
break;
// Adjusts buffer length
cbRead += cbCurr;
}
// Gets the next character
chThis = buf[cbCurr++];
// Tests for end of line
if (chThis == '\n' && fSeenCR == TRUE)
fEOLN = TRUE;
// Tests for an isolated CR
else if (fSeenCR == TRUE)
{
szBuffer[cbBuffer++] = '=';
szBuffer[cbBuffer++] = '0';
szBuffer[cbBuffer++] = 'D';
chPrev = 0xFF;
}
// CR has been taken care of
fSeenCR = FALSE;
// Tests for trailing white space if end of line
if (fEOLN == TRUE)
{
if (chPrev == ' ' || chPrev == '\t')
{
cbBuffer--;
szBuffer[cbBuffer++] = '=';
szBuffer[cbBuffer++] = rgchHex[chPrev >> 4];
szBuffer[cbBuffer++] = rgchHex[chPrev & 0x0F];
chPrev = 0xFF;
cbAttLast = cbCurr;
cbBffLast = cbBuffer;
}
}
// Tests for a must quote character
else if (((chThis < 32) && (chThis != '\r' && chThis != '\t')) || (chThis > 126 ) || (chThis == '='))
{
szBuffer[cbBuffer++] = '=';
szBuffer[cbBuffer++] = rgchHex[chThis >> 4];
szBuffer[cbBuffer++] = rgchHex[chThis & 0x0F];
chPrev = 0xFF;
}
// Tests for possible end of line
else if (chThis == '\r')
{
fSeenCR = TRUE;
}
// Other characters (includes ' ' and '\t')
else
{
// Stuffs leading '.'
if (chThis == '.' && cbBuffer == 0)
szBuffer[cbBuffer++] = '.';
szBuffer[cbBuffer++] = chThis;
chPrev = chThis;
// Tests for white space and saves location
if (chThis == ' ' || chThis == '\t')
{
cbAttLast = cbCurr;
cbBffLast = cbBuffer;
}
}
// Tests for line break
if (cbBuffer > 72 || fEOLN == TRUE || chThis == '\n')
{
// Backtracks to last whitespace
if (cbBuffer > 72 && cbBffLast > 0)
{
// RAID-33342
AssertSz(cbAttLast <= cbCurr, "Were about to eat some text.");
cbCurr = cbAttLast;
cbBuffer = cbBffLast;
}
else
{
cbAttLast = cbCurr;
cbBffLast = cbBuffer;
}
// Adds soft line break, if necessary
if (fEOLN == FALSE)
szBuffer[cbBuffer++] = '=';
// Ends line and writes to storage
szBuffer[cbBuffer++] = '\r';
szBuffer[cbBuffer++] = '\n';
// Write the buffer
CHECKHR(hr = pstmOut->Write(szBuffer, cbBuffer, NULL));
// Resets counters
fEOLN = FALSE;
cbBuffer = 0;
chPrev = 0xFF;
cbBffLast = 0;
}
}
// Writes last line to storage
if (cbBuffer > 0)
{
// Write the line
CHECKHR(hr = pstmOut->Write(szBuffer, cbBuffer, NULL));
}
exit:
// Done
return hr;
}