// QuotedPrinted.cpp: implementation of the CQuotedPrintable class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "QuotedPrinted.h"
#include "ISSHelper.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CQuotedPrintable::CQuotedPrintable()
{
m_bInline = FALSE;
}
CQuotedPrintable::~CQuotedPrintable()
{
}
int CQuotedPrintable::Decode( LPCBYTE szDecoding, LPTSTR szOutput, DWORD len )
{
if (!m_bInline)
return CMIMECode::Decode( szDecoding, szOutput, len );
if (len == MAXDWORD)
len = strlen((const char*)szDecoding);
DWORD nOut = 0;
for (DWORD lauf = 0; lauf < len; lauf++)
{
if (m_strInline.length() > 0)
{
if (strncmp((const char*)szDecoding+lauf, m_strInline.c_str(), m_strInline.length()) == 0)
{
lauf += m_strInline.length()-1;
continue;
}
}
if (szDecoding[lauf] == '=')
{
if (lauf+2 < len)
{
if (szDecoding[lauf+1] == '\r' && szDecoding[lauf+2] == '\n')
{
// Do nothing
}
else
{
if (szOutput != NULL)
szOutput[nOut++] = (HexToNum(szDecoding[lauf+1]) << 4) + HexToNum(szDecoding[lauf+2]);
else
nOut++;
}
lauf += 2;
}
}
else
{
if (szDecoding[lauf] == '_')
{
if (szOutput != NULL)
szOutput[nOut++] = ' ';
else
nOut++;
}
else
{
if (szOutput != NULL)
szOutput[nOut++] = szDecoding[lauf];
else
nOut++;
}
}
}
return nOut;
}
void CQuotedPrintable::Encode( LPCBYTE szEncoding, int nSize, string& strResult)
{
DWORD nBreak = 75;
if (!m_bInline)
{
CMIMECode::Encode( szEncoding, nSize, strResult );
return;
}
char buf[16];
strResult = _T("=?iso-8859-1?Q?");
for (int lauf = 0; lauf < nSize; lauf++)
{
buf[0] = szEncoding[lauf];
buf[1] = 0;
if (buf[0] == ' ')
buf[0] = '_';
else if ( buf[0] > 127
|| buf[0] == '='
|| !isalnum(buf[0])
)
{
sprintf(buf, "=%02X", (unsigned int)szEncoding[lauf]);
}
// special Handling
if (nBreak-strResult.length() < 2)
{
strResult += "?=\r\n\t=?iso-8859-1?Q?";
nBreak += 75;
}
strResult += buf;
}
strResult += _T("?=");
}
void CQuotedPrintable::Decode(LPSTREAM pSource, LPSTREAM pDest)
{
BYTE c;
BYTE c1;
DWORD dwRead;
do
{
pSource->Read(&c, 1, &dwRead);
if (dwRead != 1)
break;
if (c == '=')
{
pSource->Read(&c, 1, &dwRead);
if (dwRead != 1)
break;
pSource->Read(&c1, 1, &dwRead);
if (dwRead != 1)
break;
if (c == '\r' && c1 == '\n')
{
// Do nothing
}
else
{
c = (HexToNum(c) << 4) + HexToNum(c1);
pDest->Write(&c, 1, NULL);
}
}
else
{
pDest->Write(&c, 1, NULL);
}
}
while(true);
}
void CQuotedPrintable::Encode(LPSTREAM pSource, LPSTREAM pDest)
{
BYTE c;
DWORD dwRead;
char buf[128];
DWORD nBreak = 75;
int nState = 0;
BYTE nLast;
DWORD dwWritten = 0;
DWORD dwWrittenWithoutLineFeed = 0;
memset(buf, 0, sizeof(buf));
do
{
pSource->Read(&c, 1, &dwRead);
if (dwRead != 1)
{
if (strlen(buf) > 0)
{
pDest->Write(buf, strlen(buf), NULL);
dwWritten += strlen(buf);
nLast = buf[strlen(buf)-1];
}
break;
}
if (strlen(buf) > 40)
{
if (strstr(buf, "\n") != 0)
dwWrittenWithoutLineFeed = 0;
else
dwWrittenWithoutLineFeed += 20;
if (dwWrittenWithoutLineFeed > nBreak)
{
pDest->Write("=\r\n", 3, NULL);
dwWrittenWithoutLineFeed = 0;
}
pDest->Write(buf, 20, NULL);
dwWritten += 20;
memmove(buf, buf+20, sizeof(buf)-20);
}
if ( c < 9
|| (c > 9 && c < 10)
|| (c > 10 && c < 13)
|| (c > 13 && c < 32)
|| (c > 60 && c < 62)
|| c > 126
)
{
sprintf(buf+strlen(buf), "=%02X", (unsigned int)c);
}
else
{
buf[strlen(buf)] = c;
restate:
switch(nState)
{
case 0:
{
if (c == '\r')
{
nState = 1;
continue;
}
else if (c == ' ')
{
nState = 10;
continue;
}
else if (c == '\t')
{
nState = 20;
continue;
}
}
break;
case 1:
{
if (c == '\n')
{
nState = 2;
continue;
}
else
{
nState = 0;
goto restate;
}
}
break;
case 2:
{
if (c == '.')
{
nState = 3;
continue;
}
else
{
nState = 0;
goto restate;
}
}
break;
case 3:
{
if (c == '\r')
{
nState = 4;
continue;
}
else
{
nState = 0;
goto restate;
}
}
break;
case 4:
{
if (c == '\n')
{
sprintf(buf+strlen(buf)-3, "=2E\r\n");
}
else
{
nState = 0;
goto restate;
}
}
break;
case 10:
{
if (c == '\r')
{
nState = 11;
continue;
}
else
{
nState = 0;
goto restate;
}
}
break;
case 11:
{
if (c == '\n')
{
sprintf(buf+strlen(buf)-3, "=20\r\n");
}
else
{
nState = 0;
goto restate;
}
}
break;
case 20:
{
if (c == '\r')
{
nState = 21;
continue;
}
else
{
nState = 0;
goto restate;
}
}
break;
case 21:
{
if (c == '\n')
{
sprintf(buf+strlen(buf)-3, "=09\r\n");
}
else
{
nState = 0;
goto restate;
}
}
break;
default:
{
ATLASSERT(FALSE);
}
break;
}
}
if (strlen(buf) > 0)
{
if (strstr(buf, "\n") != 0)
dwWrittenWithoutLineFeed = 0;
else
dwWrittenWithoutLineFeed += strlen(buf);
if (dwWrittenWithoutLineFeed > nBreak)
{
pDest->Write("=\r\n", 3, NULL);
dwWrittenWithoutLineFeed = 0;
}
pDest->Write(buf, strlen(buf), NULL);
dwWritten += strlen(buf);
nLast = buf[strlen(buf)-1];
}
memset(buf, 0, sizeof(buf));
nState = 0;
}
while(true);
if (dwWritten > 0 && nLast != 10)
pDest->Write("\r\n", 2, NULL);
}