office-gobmx/tools/source/inet/inetstrm.cxx

1821 lines
56 KiB
C++

/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_tools.hxx"
#include <sal/types.h>
#include <rtl/memory.h>
#include <tools/cachestr.hxx>
#include <tools/debug.hxx>
#include <tools/inetmsg.hxx>
#include <tools/inetstrm.hxx>
#include <ctype.h> // toupper
inline sal_Bool SAL_CALL ascii_isWhitespace( sal_Unicode ch )
{
return ((ch <= 0x20) && ch);
}
#define CONSTASCII_STRINGPARAM(a) (a), RTL_TEXTENCODING_ASCII_US
/*=======================================================================
*
* INetMessageEncodeQPStream Interface.
* (Quoted-Printable Encoding)
*
*=====================================================================*/
class INetMessageEncodeQPStream_Impl : public INetMessageIStream
{
SvStream *pMsgStrm;
sal_uIntPtr nMsgBufSiz;
sal_Char *pMsgBuffer;
sal_Char *pMsgRead;
sal_Char *pMsgWrite;
sal_uIntPtr nTokBufSiz;
sal_Char *pTokBuffer;
sal_Char *pTokRead;
sal_Char *pTokWrite;
INetMessageStreamState eState;
sal_Bool bDone;
virtual int GetMsgLine (sal_Char *pData, sal_uIntPtr nSize);
public:
INetMessageEncodeQPStream_Impl (sal_uIntPtr nMsgBufferSize = 1024);
virtual ~INetMessageEncodeQPStream_Impl (void);
};
/*=====================================================================
*
* INetMessageDecodeQPStream Interface.
* (Quoted-Printable Decoding)
*
*====================================================================*/
class INetMessageDecodeQPStream_Impl : public INetMessageOStream
{
INetMessageStreamState eState;
SvMemoryStream *pMsgBuffer;
sal_uIntPtr nTokBufLen;
sal_Char pTokBuffer[4];
virtual int PutMsgLine (const sal_Char *pData, sal_uIntPtr nSize);
public:
INetMessageDecodeQPStream_Impl (void);
virtual ~INetMessageDecodeQPStream_Impl (void);
};
/*======================================================================
*
* INetMessageEncode64Stream Interface.
* (Base64 Encoding)
*
*====================================================================*/
class INetMessageEncode64Stream_Impl : public INetMessageIStream
{
SvStream *pMsgStrm;
sal_uIntPtr nMsgBufSiz;
sal_uInt8 *pMsgBuffer;
sal_uInt8 *pMsgRead;
sal_uInt8 *pMsgWrite;
sal_uIntPtr nTokBufSiz;
sal_Char *pTokBuffer;
sal_Char *pTokRead;
sal_Char *pTokWrite;
sal_Bool bDone;
virtual int GetMsgLine (sal_Char *pData, sal_uIntPtr nSize);
public:
INetMessageEncode64Stream_Impl (sal_uIntPtr nMsgBufferSize = 2048);
virtual ~INetMessageEncode64Stream_Impl (void);
};
/*======================================================================
*
* INetMessageDecode64Stream Interface.
* (Base64 Decoding)
*
*====================================================================*/
class INetMessageDecode64Stream_Impl : public INetMessageOStream
{
INetMessageStreamState eState;
sal_uIntPtr nMsgBufSiz;
sal_Char *pMsgBuffer;
sal_Char *pMsgRead;
sal_Char *pMsgWrite;
virtual int PutMsgLine (const sal_Char *pData, sal_uIntPtr nSize);
public:
INetMessageDecode64Stream_Impl (sal_uIntPtr nMsgBufferSize = 128);
virtual ~INetMessageDecode64Stream_Impl (void);
};
/*=========================================================================
*
* INetIStream Implementation.
*
*=======================================================================*/
/*
* INetIStream.
*/
INetIStream::INetIStream ()
{
}
/*
* ~INetIStream.
*/
INetIStream::~INetIStream (void)
{
}
/*
* Read.
*/
int INetIStream::Read (sal_Char *pData, sal_uIntPtr nSize)
{
return GetData (pData, nSize);
}
/*
* Decode64.
*/
void INetIStream::Decode64 (SvStream& rIn, SvStream& rOut)
{
INetMessage aMsg;
aMsg.SetDocumentLB(new SvAsyncLockBytes(&rOut, sal_False));
INetMessageDecode64Stream_Impl aStream (8192);
aStream.SetTargetMessage (&aMsg);
sal_Char* pBuf = new sal_Char[8192];
int nRead = 0;
while ((nRead = rIn.Read (pBuf, 8192)) > 0)
aStream.Write( pBuf, nRead );
aStream.Write ("\r\n", 2);
delete[] pBuf;
}
/*
* Encode64.
*/
void INetIStream::Encode64 (SvStream& rIn, SvStream& rOut)
{
INetMessage aMsg;
aMsg.SetDocumentLB (
new SvLockBytes (&rIn, sal_False));
INetMessageEncode64Stream_Impl aStream (8192);
aStream.SetSourceMessage (&aMsg);
sal_Char* pBuf = new sal_Char[8192];
int nRead = 0;
while ((nRead = aStream.Read (pBuf, 8192)) > 0)
rOut.Write( pBuf, nRead );
delete[] pBuf;
}
/*=========================================================================
*
* INetOStream Implementation.
*
*=======================================================================*/
/*
* INetOStream.
*/
INetOStream::INetOStream ()
{
}
/*
* ~INetOStream.
*/
INetOStream::~INetOStream (void)
{
}
/*
* Write.
*/
int INetOStream::Write (const sal_Char *pData, sal_uIntPtr nSize)
{
return PutData (pData, nSize);
}
/*=========================================================================
*
* INetMessageIStream Implementation.
*
*=======================================================================*/
/*
* INetMessageIStream.
*/
INetMessageIStream::INetMessageIStream (sal_uIntPtr nBufferSize)
: pSourceMsg (NULL),
bHeaderGenerated (sal_False),
nBufSiz (nBufferSize),
pMsgStrm (NULL),
pMsgBuffer (new SvMemoryStream)
{
pMsgBuffer->SetStreamCharSet (RTL_TEXTENCODING_ASCII_US);
pBuffer = new sal_Char[nBufSiz];
pRead = pWrite = pBuffer;
}
/*
* ~INetMessageIStream.
*/
INetMessageIStream::~INetMessageIStream (void)
{
delete [] pBuffer;
delete pMsgBuffer;
delete pMsgStrm;
}
/*
* GetData.
*/
int INetMessageIStream::GetData (sal_Char *pData, sal_uIntPtr nSize)
{
if (pSourceMsg == NULL) return INETSTREAM_STATUS_ERROR;
sal_Char *pWBuf = pData;
sal_Char *pWEnd = pData + nSize;
while (pWBuf < pWEnd)
{
// Caller's buffer not yet filled.
sal_uIntPtr n = pRead - pWrite;
if (n > 0)
{
// Bytes still in buffer.
sal_uIntPtr m = pWEnd - pWBuf;
if (m < n) n = m;
for (sal_uIntPtr i = 0; i < n; i++) *pWBuf++ = *pWrite++;
}
else
{
// Buffer empty. Reset to <Begin-of-Buffer>.
pRead = pWrite = pBuffer;
// Read next message line.
int nRead = GetMsgLine (pBuffer, nBufSiz);
if (nRead > 0)
{
// Set read pointer.
pRead = pBuffer + nRead;
}
else
{
if (!bHeaderGenerated)
{
// Header generated. Insert empty line.
bHeaderGenerated = sal_True;
*pRead++ = '\r';
*pRead++ = '\n';
}
else
{
// Body generated.
return (pWBuf - pData);
}
}
}
}
return (pWBuf - pData);
}
/*
* GetMsgLine.
*/
int INetMessageIStream::GetMsgLine (sal_Char *pData, sal_uIntPtr nSize)
{
if (pSourceMsg == NULL) return INETSTREAM_STATUS_ERROR;
sal_Char *pWBuf = pData;
sal_Char *pWEnd = pData + nSize;
if (!bHeaderGenerated)
{
sal_uIntPtr i, n;
if (pMsgBuffer->Tell() == 0)
{
// Insert formatted header into buffer.
n = pSourceMsg->GetHeaderCount();
for (i = 0; i < n; i++)
{
INetMessageHeader aHeader (pSourceMsg->GetHeaderField(i));
if (aHeader.GetValue().Len())
{
// NYI: Folding long lines.
*pMsgBuffer << (sal_Char*)(aHeader.GetName().GetBuffer());
*pMsgBuffer << ": ";
*pMsgBuffer << (sal_Char*)(aHeader.GetValue().GetBuffer());
*pMsgBuffer << "\r\n";
}
}
pMsgWrite = (sal_Char *)(pMsgBuffer->GetData());
pMsgRead = pMsgWrite + pMsgBuffer->Tell();
}
n = pMsgRead - pMsgWrite;
if (n > 0)
{
// Move to caller.
if (nSize < n) n = nSize;
for (i = 0; i < n; i++) *pWBuf++ = *pMsgWrite++;
}
else
{
// Reset buffer.
pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
}
}
else
{
if (pSourceMsg->GetDocumentLB())
{
if (pMsgStrm == NULL)
pMsgStrm = new SvStream (pSourceMsg->GetDocumentLB());
sal_uIntPtr nRead = pMsgStrm->Read (pWBuf, (pWEnd - pWBuf));
pWBuf += nRead;
}
}
return (pWBuf - pData);
}
/*=========================================================================
*
* INetMessageOStream Implementation.
*
*=======================================================================*/
/*
* INetMessageOStream.
*/
INetMessageOStream::INetMessageOStream (void)
: pTargetMsg (NULL),
bHeaderParsed (sal_False),
eOState (INETMSG_EOL_BEGIN),
pMsgBuffer (new SvMemoryStream)
{
}
/*
* ~INetMessageOStream.
*/
INetMessageOStream::~INetMessageOStream (void)
{
if (pMsgBuffer->Tell() > 0)
PutMsgLine ((const sal_Char *) pMsgBuffer->GetData(), pMsgBuffer->Tell());
delete pMsgBuffer;
if (pTargetMsg)
{
SvOpenLockBytes *pLB =
PTR_CAST (SvOpenLockBytes, pTargetMsg->GetDocumentLB());
if (pLB)
{
pLB->Flush();
pLB->Terminate();
}
}
}
/*
* PutData.
* (Simple Field Parsing (RFC822, Appendix B)).
*/
int INetMessageOStream::PutData (const sal_Char *pData, sal_uIntPtr nSize)
{
if (pTargetMsg == NULL) return INETSTREAM_STATUS_ERROR;
const sal_Char *pStop = (pData + nSize);
while (!bHeaderParsed && (pData < pStop))
{
if (eOState == INETMSG_EOL_BEGIN)
{
if ((*pData == '\r') || (*pData == '\n'))
{
/*
* Empty Line. Separates header fields from message body.
* Skip this and any 2nd line break character (if any).
*/
pData++;
if ((pData < pStop) && ((*pData == '\r') || (*pData == '\n')))
pData++;
// Emit any buffered last header field.
if (pMsgBuffer->Tell() > 0)
{
*pMsgBuffer << '\0';
int status = PutMsgLine (
(const sal_Char *) pMsgBuffer->GetData(),
pMsgBuffer->Tell());
if (status != INETSTREAM_STATUS_OK) return status;
}
// Reset to begin.
eOState = INETMSG_EOL_BEGIN;
pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
// Mark header parsed.
bHeaderParsed = sal_True;
}
else if ((*pData == ' ') || (*pData == '\t'))
{
// Continuation line. Unfold multi-line field-body.
*pMsgBuffer << ' ';
pData++;
}
else
{
// Begin of new header field.
if (pMsgBuffer->Tell() > 0)
{
// Emit buffered header field now.
*pMsgBuffer << '\0';
int status = PutMsgLine (
(const sal_Char *) pMsgBuffer->GetData(),
pMsgBuffer->Tell());
if (status != INETSTREAM_STATUS_OK) return status;
}
// Reset to begin of buffer.
pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
// Insert current character into buffer.
*pMsgBuffer << *pData++;
}
// Search for next line break character.
if (!bHeaderParsed) eOState = INETMSG_EOL_SCR;
}
else if (eOState == INETMSG_EOL_FCR)
{
// Skip line break character.
pData++;
// Mark begin of line.
eOState = INETMSG_EOL_BEGIN;
}
else if ((*pData == '\r') || (*pData == '\n'))
{
if (*pData == '\r') pData++;
eOState = INETMSG_EOL_FCR;
}
else if (ascii_isWhitespace (*pData & 0x7f))
{
// Any <LWS> is folded into a single <SP> character.
sal_Char c = *((const sal_Char *) pMsgBuffer->GetData() + pMsgBuffer->Tell() - 1);
if (!ascii_isWhitespace (c & 0x7f)) *pMsgBuffer << ' ';
// Skip over this <LWS> character.
pData++;
}
else
{
// Any other character is inserted into line buffer.
*pMsgBuffer << *pData++;
}
}
if (bHeaderParsed && (pData < pStop))
{
// Put message body down-stream.
return PutMsgLine (pData, (pStop - pData));
}
return INETSTREAM_STATUS_OK;
}
/*
* PutMsgLine.
*/
int INetMessageOStream::PutMsgLine (const sal_Char *pData, sal_uIntPtr nSize)
{
// Check for message container.
if (pTargetMsg == NULL) return INETSTREAM_STATUS_ERROR;
// Check for header or body.
if (!IsHeaderParsed())
{
ByteString aField (pData);
sal_uInt16 nPos = aField.Search (':');
if (nPos != STRING_NOTFOUND)
{
ByteString aName (
aField.Copy (0, nPos));
ByteString aValue (
aField.Copy (nPos + 1, aField.Len() - nPos + 1));
aValue.EraseLeadingChars (' ');
pTargetMsg->SetHeaderField (
INetMessageHeader (aName, aValue));
}
}
else
{
SvOpenLockBytes *pLB =
PTR_CAST(SvOpenLockBytes, pTargetMsg->GetDocumentLB());
if (pLB == NULL)
return INETSTREAM_STATUS_WOULDBLOCK;
sal_Size nDocSiz = pTargetMsg->GetDocumentSize();
sal_Size nWrite = 0;
pLB->FillAppend ((sal_Char *)pData, nSize, &nWrite);
pTargetMsg->SetDocumentSize (nDocSiz + nWrite);
if (nWrite < nSize) return INETSTREAM_STATUS_ERROR;
}
return INETSTREAM_STATUS_OK;
}
/*=========================================================================
*
* INetMessageIOStream Implementation.
*
*=======================================================================*/
/*
* INetMessageIOStream.
*/
INetMessageIOStream::INetMessageIOStream (sal_uIntPtr nBufferSize)
: INetMessageIStream (nBufferSize),
INetMessageOStream ()
{
}
/*
* ~INetMessageIOStream.
*/
INetMessageIOStream::~INetMessageIOStream (void)
{
}
/*=======================================================================
*
* INetMessageEncodeQPStream_Impl Implementation.
* (Quoted-Printable Encoding)
*
*=====================================================================*/
static const sal_Char hex2pr[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'
};
static const sal_Char ebcdic[] = {
'!', '"', '#', '$', '@', '[', '\\', ']', '^', '`', '{', '|', '}', '~'
};
/*
* INetMessageEncodeQPStream_Impl.
*/
INetMessageEncodeQPStream_Impl::INetMessageEncodeQPStream_Impl (
sal_uIntPtr nMsgBufferSize)
: INetMessageIStream (),
pMsgStrm (NULL),
nMsgBufSiz (nMsgBufferSize),
nTokBufSiz (80),
eState (INETMSG_EOL_SCR),
bDone (sal_False)
{
GenerateHeader (sal_False);
pMsgBuffer = new sal_Char[nMsgBufSiz];
pMsgRead = pMsgWrite = pMsgBuffer;
pTokBuffer = new sal_Char[nTokBufSiz];
pTokRead = pTokWrite = pTokBuffer;
}
/*
* ~INetMessageEncodeQPStream_Impl.
*/
INetMessageEncodeQPStream_Impl::~INetMessageEncodeQPStream_Impl (void)
{
delete pMsgStrm;
delete [] pMsgBuffer;
delete [] pTokBuffer;
}
/*
* GetMsgLine.
*/
int INetMessageEncodeQPStream_Impl::GetMsgLine (sal_Char *pData, sal_uIntPtr nSize)
{
INetMessage *pMsg = GetSourceMessage ();
if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
if (pMsg->GetDocumentLB() == NULL) return 0;
if (pMsgStrm == NULL) pMsgStrm = new SvStream (pMsg->GetDocumentLB());
sal_Char *pWBuf = pData;
while (pWBuf < (pData + nSize))
{
// Caller's buffer not yet filled.
if ((pMsgRead - pMsgWrite) > 0)
{
// Bytes still in message buffer.
if ((eState != INETMSG_EOL_BEGIN) &&
((pTokRead - pTokBuffer) < 72))
{
// Token buffer not yet filled.
if (eState == INETMSG_EOL_FCR)
{
eState = INETMSG_EOL_BEGIN;
if (*pMsgWrite != '\n')
{
// Convert orphant <CR> into <CR><LF> sequence.
*pTokRead++ = '\n';
}
*pTokRead++ = *pMsgWrite++;
}
else if ((*pMsgWrite == ' ') || (*pMsgWrite == '\t'))
{
eState = INETMSG_EOL_FSP;
*pTokRead++ = *pMsgWrite++;
}
else if (*pMsgWrite == '\r')
{
// Found <CR>.
if (eState == INETMSG_EOL_FSP)
{
// Encode last (trailing space) character.
sal_uInt8 c = (sal_uInt8)(*(--pTokRead));
*pTokRead++ = '=';
*pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
*pTokRead++ = hex2pr[((c & 0x0f) )];
}
eState = INETMSG_EOL_FCR;
*pTokRead++ = *pMsgWrite++;
}
else if (*pMsgWrite == '\n')
{
// Found <LF> only.
if (eState == INETMSG_EOL_FSP)
{
// Encode last (trailing space) character.
sal_uInt8 c = (sal_uInt8)(*(--pTokRead));
*pTokRead++ = '=';
*pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
*pTokRead++ = hex2pr[((c & 0x0f) )];
}
eState = INETMSG_EOL_BEGIN;
// Convert orphant <LF> into <CR><LF> sequence.
*pTokRead++ = '\r';
*pTokRead++ = *pMsgWrite++;
}
else if (*pMsgWrite == '=')
{
// Escape character itself MUST be encoded, of course.
sal_uInt8 c = (sal_uInt8)(*pMsgWrite++);
*pTokRead++ = '=';
*pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
*pTokRead++ = hex2pr[((c & 0x0f) )];
eState = INETMSG_EOL_SCR;
}
else if (((sal_uInt8)(*pMsgWrite) > 0x20) &&
((sal_uInt8)(*pMsgWrite) < 0x7f) )
{
/*
* Some printable ASCII character.
* (Encode EBCDIC special characters (NYI)).
*/
*pTokRead++ = *pMsgWrite++;
eState = INETMSG_EOL_SCR;
}
else
{
// Encode any other character.
sal_uInt8 c = (sal_uInt8)(*pMsgWrite++);
*pTokRead++ = '=';
*pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
*pTokRead++ = hex2pr[((c & 0x0f) )];
eState = INETMSG_EOL_SCR;
}
}
else
{
// Check for maximum line length.
if (eState != INETMSG_EOL_BEGIN)
{
// Insert soft line break.
*pTokRead++ = '=';
*pTokRead++ = '\r';
*pTokRead++ = '\n';
eState = INETMSG_EOL_BEGIN;
}
// Copy to caller's buffer.
if ((pTokRead - pTokWrite) > 0)
{
// Bytes still in token buffer.
*pWBuf++ = *pTokWrite++;
}
else
{
// Token buffer empty. Reset to <Begin-of-Buffer>.
pTokRead = pTokWrite = pTokBuffer;
eState = INETMSG_EOL_SCR;
}
}
}
else
{
// Message buffer empty. Reset to <Begin-of-Buffer>.
pMsgRead = pMsgWrite = pMsgBuffer;
// Read next message block.
sal_uIntPtr nRead = pMsgStrm->Read (pMsgBuffer, nMsgBufSiz);
if (nRead > 0)
{
// Set read pointer.
pMsgRead = (pMsgBuffer + nRead);
}
else
{
// Nothing more ro read.
if (!bDone)
{
// Append final <CR><LF> and mark we're done.
*pTokRead++ = '\r';
*pTokRead++ = '\n';
bDone = sal_True;
}
else
{
// Already done all encoding.
if ((pTokRead - pTokWrite) > 0)
{
// Bytes still in token buffer.
*pWBuf++ = *pTokWrite++;
}
else
{
// Token buffer empty. Reset to <Begin-of-Buffer>.
pTokRead = pTokWrite = pTokBuffer;
// Return.
return (pWBuf - pData);
}
}
}
}
}
return (pWBuf - pData);
}
/*=====================================================================
*
* INetMessageDecodeQPStream_Impl Implementation.
* (Quoted-Printable Decoding)
*
*====================================================================*/
static const sal_uInt8 pr2hex[128] = {
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
};
/*
* INetMessageDecodeQPStream_Impl.
*/
INetMessageDecodeQPStream_Impl::INetMessageDecodeQPStream_Impl (void)
: INetMessageOStream (),
eState (INETMSG_EOL_BEGIN),
pMsgBuffer (new SvMemoryStream),
nTokBufLen (0)
{
ParseHeader (sal_False);
}
/*
* ~INetMessageDecodeQPStream_Impl.
*/
INetMessageDecodeQPStream_Impl::~INetMessageDecodeQPStream_Impl (void)
{
delete pMsgBuffer;
}
/*
* PutMsgLine.
*/
int INetMessageDecodeQPStream_Impl::PutMsgLine (
const sal_Char *pData, sal_uIntPtr nSize)
{
INetMessage *pMsg = GetTargetMessage();
if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
SvOpenLockBytes * pLB = PTR_CAST(SvOpenLockBytes, pMsg->GetDocumentLB());
if (pLB == NULL) return INETSTREAM_STATUS_WOULDBLOCK;
const sal_Char *pStop = pData + nSize;
while (pData < pStop)
{
if (eState == INETMSG_EOL_FESC)
{
*(pTokBuffer + nTokBufLen++) = static_cast< char >(toupper(*pData));
pData++;
if (nTokBufLen == 2)
{
if ((*pTokBuffer == '\r') || (*pTokBuffer == '\n'))
{
// Soft line break (=<CR><LF>). Emit buffer now.
eState = INETMSG_EOL_BEGIN;
}
else
{
// Decode token.
*pMsgBuffer << sal_uInt8 (
(pr2hex[(int)(pTokBuffer[0] & 0x7f)] << 4) |
(pr2hex[(int)(pTokBuffer[1] & 0x7f)] & 15) );
// Search for next <CR>.
eState = INETMSG_EOL_SCR;
}
// Reset token buffer.
nTokBufLen = 0;
}
}
else if (*pData == '=')
{
// Found escape character.
pData++;
eState = INETMSG_EOL_FESC;
}
else if (eState == INETMSG_EOL_FCR)
{
*pMsgBuffer << *pData++;
eState = INETMSG_EOL_BEGIN;
}
else if (*pData == '\r')
{
*pMsgBuffer << *pData++;
eState = INETMSG_EOL_FCR;
}
else
{
*pMsgBuffer << *pData++;
}
if (eState == INETMSG_EOL_BEGIN)
{
sal_Size nRead = pMsgBuffer->Tell();
if (nRead > 0)
{
// Emit buffer.
sal_Size nDocSiz = pMsg->GetDocumentSize();
sal_Size nWrite = 0;
pLB->FillAppend (
(sal_Char *)(pMsgBuffer->GetData()), nRead, &nWrite);
pMsg->SetDocumentSize (nDocSiz + nWrite);
if (nWrite < nRead) return INETSTREAM_STATUS_ERROR;
pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
}
eState = INETMSG_EOL_SCR;
}
}
return INETSTREAM_STATUS_OK;
}
/*======================================================================
*
* INetMessageEncode64Stream_Impl Implementation.
* (Base64 Encoding)
*
*====================================================================*/
static const sal_Char six2pr[64] = {
'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', '+', '/'
};
/*
* INetMessageEncode64Stream_Impl.
*/
INetMessageEncode64Stream_Impl::INetMessageEncode64Stream_Impl (
sal_uIntPtr nMsgBufferSize)
: INetMessageIStream (),
pMsgStrm (NULL),
nMsgBufSiz (nMsgBufferSize),
nTokBufSiz (80),
bDone (sal_False)
{
GenerateHeader (sal_False);
pMsgBuffer = new sal_uInt8[nMsgBufSiz];
pMsgRead = pMsgWrite = pMsgBuffer;
pTokBuffer = new sal_Char[nTokBufSiz];
pTokRead = pTokWrite = pTokBuffer;
}
/*
* ~INetMessageEncode64Stream_Impl.
*/
INetMessageEncode64Stream_Impl::~INetMessageEncode64Stream_Impl (void)
{
delete pMsgStrm;
delete [] pMsgBuffer;
delete [] pTokBuffer;
}
/*
* GetMsgLine.
*/
int INetMessageEncode64Stream_Impl::GetMsgLine (sal_Char *pData, sal_uIntPtr nSize)
{
INetMessage *pMsg = GetSourceMessage ();
if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
if (pMsg->GetDocumentLB() == NULL) return 0;
if (pMsgStrm == NULL) pMsgStrm = new SvStream (pMsg->GetDocumentLB());
sal_Char *pWBuf = pData;
while (pWBuf < (pData + nSize))
{
// Caller's buffer not yet filled.
if ((pMsgRead - pMsgWrite) > 0)
{
// Bytes still in message buffer.
if ((pTokRead - pTokBuffer) < 72)
{
// Token buffer not yet filled.
switch ((pTokRead - pTokBuffer) % 4)
{
case 0:
*pTokRead++ = six2pr[(int)(*pMsgWrite >> 2)];
break;
case 1:
*pTokRead++ = six2pr[
(int)(((*pMsgWrite << 4) & 060) |
(((*(pMsgWrite + 1)) >> 4) & 017))];
pMsgWrite++;
break;
case 2:
*pTokRead++ = six2pr[
(int)(((*pMsgWrite << 2) & 074) |
(((*(pMsgWrite + 1)) >> 6) & 003))];
pMsgWrite++;
break;
default: // == case 3
*pTokRead++ = six2pr[(int)(*pMsgWrite & 077)];
pMsgWrite++;
break;
}
}
else if ((pTokRead - pTokBuffer) == 72)
{
// Maximum line length. Append <CR><LF>.
*pTokRead++ = '\r';
*pTokRead++ = '\n';
}
else
{
if ((pTokRead - pTokWrite) > 0)
{
// Bytes still in token buffer.
*pWBuf++ = *pTokWrite++;
}
else
{
// Token buffer empty. Reset to <Begin-of-Buffer>.
pTokRead = pTokWrite = pTokBuffer;
}
}
}
else
{
// Message buffer empty. Reset to <Begin-of-Buffer>.
pMsgRead = pMsgWrite = pMsgBuffer;
// Read next message block.
sal_uIntPtr nRead = pMsgStrm->Read (pMsgBuffer, nMsgBufSiz);
if (nRead > 0)
{
// Set read pointer.
pMsgRead = (pMsgBuffer + nRead);
}
else
{
// Nothing more to read.
if (!bDone)
{
// Append pad character(s) and final <CR><LF>.
switch ((pTokRead - pTokBuffer) % 4)
{
case 2:
*pTokRead++ = '=';
// Fall through for 2nd pad character.
case 3:
*pTokRead++ = '=';
break;
default:
break;
}
*pTokRead++ = '\r';
*pTokRead++ = '\n';
// Mark we're done.
bDone = sal_True;
}
else
{
// Already done all encoding.
if ((pTokRead - pTokWrite) > 0)
{
// Bytes still in token buffer.
*pWBuf++ = *pTokWrite++;
}
else
{
// Token buffer empty. Reset to <Begin-of-Buffer>.
pTokRead = pTokWrite = pTokBuffer;
// Reset done flag, if everything has been done.
// if (pWBuf == pData) bDone = sal_False;
// Return.
return (pWBuf - pData);
}
}
}
}
} // while (pWBuf < (pData + nSize))
return (pWBuf - pData);
}
/*======================================================================
*
* INetMessageDecode64Stream_Impl Implementation.
* (Base64 Decoding)
*
*====================================================================*/
static const sal_uInt8 pr2six[256] = {
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x3E, 0x40, 0x40, 0x40, 0x3F,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
0x3C, 0x3D, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
0x31, 0x32, 0x33, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
};
/*
* INetMessageDecode64Stream_Impl.
*/
INetMessageDecode64Stream_Impl::INetMessageDecode64Stream_Impl (
sal_uIntPtr nMsgBufferSize)
: INetMessageOStream (),
eState (INETMSG_EOL_SCR),
nMsgBufSiz (nMsgBufferSize)
{
ParseHeader (sal_False);
pMsgBuffer = new sal_Char[nMsgBufSiz];
pMsgRead = pMsgWrite = pMsgBuffer;
}
/*
* ~INetMessageDecode64Stream_Impl.
*/
INetMessageDecode64Stream_Impl::~INetMessageDecode64Stream_Impl (void)
{
delete [] pMsgBuffer;
}
/*
* PutMsgLine.
*/
int INetMessageDecode64Stream_Impl::PutMsgLine (
const sal_Char *pData, sal_uIntPtr nSize)
{
INetMessage *pMsg = GetTargetMessage ();
if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
SvOpenLockBytes * pLB = PTR_CAST(SvOpenLockBytes, pMsg->GetDocumentLB());
if (pLB == NULL) return INETSTREAM_STATUS_WOULDBLOCK;
const sal_Char *pStop = (pData + nSize);
while (pData < pStop)
{
if (pr2six[(int)(*pData)] > 63)
{
/*
* Character not in base64 alphabet.
* Check for <End-of-Stream> or Junk.
*/
if (*pData == '=')
{
// Final pad character -> Done.
sal_Size nDocSiz = pMsg->GetDocumentSize();
sal_Size nRead = pMsgWrite - pMsgBuffer;
sal_Size nWrite = 0;
pLB->FillAppend (pMsgBuffer, nRead, &nWrite);
pMsg->SetDocumentSize (nDocSiz + nWrite);
if (nWrite < nRead)
return INETSTREAM_STATUS_ERROR;
else
return INETSTREAM_STATUS_LOADED;
}
else if (eState == INETMSG_EOL_FCR)
{
// Skip any line break character.
if ((*pData == '\r') || (*pData == '\n')) pData++;
// Store decoded message buffer contents.
sal_Size nDocSiz = pMsg->GetDocumentSize();
sal_Size nRead = pMsgWrite - pMsgBuffer;
sal_Size nWrite = 0;
pLB->FillAppend (pMsgBuffer, nRead, &nWrite);
pMsg->SetDocumentSize (nDocSiz + nWrite);
if (nWrite < nRead) return INETSTREAM_STATUS_ERROR;
// Reset to <Begin-of-Buffer>.
pMsgWrite = pMsgBuffer;
eState = INETMSG_EOL_SCR;
}
else if ((*pData == '\r') || (*pData == '\n'))
{
// Skip any line break character.
pData++;
eState = INETMSG_EOL_FCR;
}
else
{
// Skip any junk character (may be transmission error).
pData++;
}
}
else
{
// Decode any other character into message buffer.
switch ((pMsgRead - pMsgBuffer) % 4)
{
case 0:
*pMsgWrite = (pr2six[(int)(*pData++)] << 2);
pMsgRead++;
break;
case 1:
*pMsgWrite++ |= (pr2six[(int)(*pData )] >> 4);
*pMsgWrite = (pr2six[(int)(*pData++)] << 4);
pMsgRead++;
break;
case 2:
*pMsgWrite++ |= (pr2six[(int)(*pData )] >> 2);
*pMsgWrite = (pr2six[(int)(*pData++)] << 6);
pMsgRead++;
break;
default: // == case 3
*pMsgWrite++ |= (pr2six[(int)(*pData++)]);
pMsgRead = pMsgBuffer;
break;
} // switch ((pMsgRead - pMsgBuffer) % 4)
}
} // while (pData < pStop)
return INETSTREAM_STATUS_OK;
}
/*=========================================================================
*
* INetMIMEMessageStream Implementation.
*
*=======================================================================*/
/*
* INetMIMEMessageStream.
*/
INetMIMEMessageStream::INetMIMEMessageStream (sal_uIntPtr nBufferSize)
: INetMessageIOStream (nBufferSize),
eState (INETMSG_EOL_BEGIN),
nChildIndex (0),
pChildStrm (NULL),
eEncoding (INETMSG_ENCODING_BINARY),
pEncodeStrm (NULL),
pDecodeStrm (NULL),
pMsgBuffer (NULL)
{
}
/*
* ~INetMIMEMessageStream.
*/
INetMIMEMessageStream::~INetMIMEMessageStream (void)
{
delete pChildStrm;
delete pEncodeStrm;
delete pDecodeStrm;
delete pMsgBuffer;
}
/*
* GetMsgEncoding.
*/
INetMessageEncoding
INetMIMEMessageStream::GetMsgEncoding (const String& rContentType)
{
if ((rContentType.CompareIgnoreCaseToAscii ("message" , 7) == 0) ||
(rContentType.CompareIgnoreCaseToAscii ("multipart", 9) == 0) )
return INETMSG_ENCODING_7BIT;
if (rContentType.CompareIgnoreCaseToAscii ("text", 4) == 0)
{
if (rContentType.CompareIgnoreCaseToAscii ("text/plain", 10) == 0)
{
if (rContentType.GetTokenCount ('=') > 1)
{
String aCharset (rContentType.GetToken (1, '='));
aCharset.EraseLeadingChars (' ');
aCharset.EraseLeadingChars ('"');
if (aCharset.CompareIgnoreCaseToAscii ("us-ascii", 8) == 0)
return INETMSG_ENCODING_7BIT;
else
return INETMSG_ENCODING_QUOTED;
}
else
return INETMSG_ENCODING_7BIT;
}
else
return INETMSG_ENCODING_QUOTED;
}
return INETMSG_ENCODING_BASE64;
}
/*
* GetMsgLine.
* (Message Generator).
*/
int INetMIMEMessageStream::GetMsgLine (sal_Char *pData, sal_uIntPtr nSize)
{
// Check for message container.
INetMIMEMessage *pMsg = GetSourceMessage();
if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
// Check for header or body.
if (!IsHeaderGenerated())
{
if (eState == INETMSG_EOL_BEGIN)
{
// Prepare special header fields.
if (pMsg->GetParent())
{
String aPCT (pMsg->GetParent()->GetContentType());
if (aPCT.CompareIgnoreCaseToAscii ("message/rfc822", 14) == 0)
pMsg->SetMIMEVersion (
String(CONSTASCII_STRINGPARAM("1.0")));
else
pMsg->SetMIMEVersion (String());
}
else
{
pMsg->SetMIMEVersion (String(CONSTASCII_STRINGPARAM("1.0")));
}
// Check ContentType.
String aContentType (pMsg->GetContentType());
if (aContentType.Len())
{
// Determine default Content-Type.
String aDefaultType;
pMsg->GetDefaultContentType (aDefaultType);
if (aDefaultType.CompareIgnoreCaseToAscii (
aContentType, aContentType.Len()) == 0)
{
// No need to specify default.
pMsg->SetContentType (String());
}
}
// Check Encoding.
String aEncoding (pMsg->GetContentTransferEncoding());
if (aEncoding.Len())
{
// Use given Encoding.
if (aEncoding.CompareIgnoreCaseToAscii (
"base64", 6) == 0)
eEncoding = INETMSG_ENCODING_BASE64;
else if (aEncoding.CompareIgnoreCaseToAscii (
"quoted-printable", 16) == 0)
eEncoding = INETMSG_ENCODING_QUOTED;
else
eEncoding = INETMSG_ENCODING_7BIT;
}
else
{
// Use default Encoding for (given|default) Content-Type.
if (aContentType.Len() == 0)
{
// Determine default Content-Type.
pMsg->GetDefaultContentType (aContentType);
}
eEncoding = GetMsgEncoding (aContentType);
}
// Set Content-Transfer-Encoding header.
if (eEncoding == INETMSG_ENCODING_BASE64)
{
// Base64.
pMsg->SetContentTransferEncoding (
String(CONSTASCII_STRINGPARAM("base64")));
}
else if (eEncoding == INETMSG_ENCODING_QUOTED)
{
// Quoted-Printable.
pMsg->SetContentTransferEncoding (
String(CONSTASCII_STRINGPARAM("quoted-printable")));
}
else
{
// No need to specify default.
pMsg->SetContentTransferEncoding (String());
}
// Mark we're done.
eState = INETMSG_EOL_DONE;
}
// Generate the message header.
int nRead = INetMessageIOStream::GetMsgLine (pData, nSize);
if (nRead <= 0)
{
// Reset state.
eState = INETMSG_EOL_BEGIN;
}
return nRead;
}
else
{
// Generate the message body.
if (pMsg->IsContainer())
{
// Encapsulated message body.
while (eState == INETMSG_EOL_BEGIN)
{
if (pChildStrm == NULL)
{
INetMIMEMessage *pChild = pMsg->GetChild (nChildIndex);
if (pChild)
{
// Increment child index.
nChildIndex++;
// Create child stream.
pChildStrm = new INetMIMEMessageStream;
pChildStrm->SetSourceMessage (pChild);
if (pMsg->IsMultipart())
{
// Insert multipart delimiter.
ByteString aDelim ("--");
aDelim += pMsg->GetMultipartBoundary();
aDelim += "\r\n";
rtl_copyMemory (
pData, aDelim.GetBuffer(), aDelim.Len());
return aDelim.Len();
}
}
else
{
// No more parts. Mark we're done.
eState = INETMSG_EOL_DONE;
nChildIndex = 0;
if (pMsg->IsMultipart())
{
// Insert close delimiter.
ByteString aDelim ("--");
aDelim += pMsg->GetMultipartBoundary();
aDelim += "--\r\n";
rtl_copyMemory (
pData, aDelim.GetBuffer(), aDelim.Len());
return aDelim.Len();
}
}
}
else
{
// Read current child stream.
int nRead = pChildStrm->Read (pData, nSize);
if (nRead > 0)
{
return nRead;
}
else
{
// Cleanup exhausted child stream.
delete pChildStrm;
pChildStrm = NULL;
}
}
}
return 0;
}
else
{
// Single part message body.
if (pMsg->GetDocumentLB() == NULL)
{
// Empty message body.
return 0;
}
else
{
// Check whether message body needs to be encoded.
if (eEncoding == INETMSG_ENCODING_7BIT)
{
// No Encoding.
return INetMessageIOStream::GetMsgLine (pData, nSize);
}
else
{
// Apply appropriate Encoding.
while (eState == INETMSG_EOL_BEGIN)
{
if (pEncodeStrm == NULL)
{
// Create encoder stream.
if (eEncoding == INETMSG_ENCODING_QUOTED)
{
// Quoted-Printable Encoding.
pEncodeStrm
= new INetMessageEncodeQPStream_Impl;
}
else
{
// Base64 Encoding.
pEncodeStrm
= new INetMessageEncode64Stream_Impl;
}
pEncodeStrm->SetSourceMessage (pMsg);
}
// Read encoded message.
int nRead = pEncodeStrm->Read (pData, nSize);
if (nRead > 0)
{
return nRead;
}
else
{
// Cleanup exhausted encoder stream.
delete pEncodeStrm;
pEncodeStrm = NULL;
// Mark we're done.
eState = INETMSG_EOL_DONE;
}
}
return 0;
}
}
}
}
}
/*
* PutMsgLine.
* (Message Parser).
*/
int INetMIMEMessageStream::PutMsgLine (const sal_Char *pData, sal_uIntPtr nSize)
{
// Check for message container.
INetMIMEMessage *pMsg = GetTargetMessage();
if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
// Check for header or body.
if (!IsHeaderParsed())
{
// Parse the message header.
int nRet = INetMessageIOStream::PutMsgLine (pData, nSize);
return nRet;
}
else
{
pMsg->SetHeaderParsed();
// Parse the message body.
if (pMsg->IsContainer())
{
// Content-Transfer-Encoding MUST be "7bit" (RFC1521).
if (pMsg->IsMessage())
{
if( !pChildStrm )
{
// Encapsulated message.
pMsg->SetChildCount( pMsg->GetChildCount() + 1);
INetMIMEMessage* pNewMessage = new INetMIMEMessage;
pNewMessage->SetDocumentLB (
new SvAsyncLockBytes(new SvCacheStream, sal_False));
pMsg->AttachChild( *pNewMessage, sal_True );
// Encapsulated message body. Create message parser stream.
pChildStrm = new INetMIMEMessageStream;
pChildStrm->SetTargetMessage ( pNewMessage );
// Initialize control variables.
eState = INETMSG_EOL_BEGIN;
}
if ( nSize > 0)
{
// Bytes still in buffer. Put message down-stream.
int status = pChildStrm->Write( pData, nSize );
if (status != INETSTREAM_STATUS_OK)
return status;
}
return INetMessageIOStream::PutMsgLine (pData, nSize);
}
else
{
// Multipart message body. Initialize multipart delimiters.
// Multipart message.
if (pMsg->GetMultipartBoundary().Len() == 0)
{
// Determine boundary.
ByteString aType (
pMsg->GetContentType(), RTL_TEXTENCODING_ASCII_US);
ByteString aLowerType (aType);
aLowerType.ToLowerAscii();
sal_uInt16 nPos = aLowerType.Search ("boundary=");
ByteString aBoundary (aType.Copy (nPos + 9));
aBoundary.EraseLeadingAndTrailingChars (' ');
aBoundary.EraseLeadingAndTrailingChars ('"');
// Save boundary.
pMsg->SetMultipartBoundary (aBoundary);
}
ByteString aPlainDelim (pMsg->GetMultipartBoundary());
ByteString aDelim ("--");
aDelim += aPlainDelim;
ByteString aPlainClose (aPlainDelim);
aPlainClose += "--";
ByteString aClose (aDelim);
aClose += "--";
if (pMsgBuffer == NULL) pMsgBuffer = new SvMemoryStream;
pMsgBuffer->Write (pData, nSize);
sal_uIntPtr nBufSize = pMsgBuffer->Tell();
const sal_Char* pChar;
const sal_Char* pOldPos;
for( pOldPos = pChar = (const sal_Char *) pMsgBuffer->GetData(); nBufSize--;
pChar++ )
{
int status;
if( *pChar == '\r' || *pChar == '\n' )
{
if( aDelim.CompareTo (pOldPos, aDelim.Len())
!= COMPARE_EQUAL &&
aClose.CompareTo (pOldPos, aClose.Len())
!= COMPARE_EQUAL &&
aPlainDelim.CompareTo (pOldPos, aPlainDelim.Len())
!= COMPARE_EQUAL &&
aPlainClose.CompareTo(pOldPos, aPlainClose.Len())
!= COMPARE_EQUAL )
{
if( nBufSize &&
( pChar[1] == '\r' || pChar[1] == '\n' ) )
nBufSize--, pChar++;
if( pChildStrm )
{
status = pChildStrm->Write(
pOldPos, pChar - pOldPos + 1 );
if( status != INETSTREAM_STATUS_OK )
return status;
}
else {
DBG_ERRORFILE( "Die Boundary nicht gefunden" );
}
status = INetMessageIOStream::PutMsgLine(
pOldPos, pChar - pOldPos + 1 );
if( status != INETSTREAM_STATUS_OK )
return status;
pOldPos = pChar + 1;
}
else
{
if( nBufSize &&
( pChar[1] == '\r' || pChar[1] == '\n' ) )
nBufSize--, pChar++;
pOldPos = pChar + 1;
DELETEZ( pChildStrm );
if (aClose.CompareTo (pOldPos, aClose.Len())
!= COMPARE_EQUAL &&
aPlainClose.CompareTo (pOldPos, aClose.Len())
!= COMPARE_EQUAL )
{
// Encapsulated message.
pMsg->SetChildCount(pMsg->GetChildCount() + 1);
INetMIMEMessage* pNewMessage =
new INetMIMEMessage;
pNewMessage->SetDocumentLB (
new SvAsyncLockBytes (
new SvCacheStream, sal_False));
pMsg->AttachChild( *pNewMessage, sal_True );
// Encapsulated message body. Create message parser stream.
pChildStrm = new INetMIMEMessageStream;
pChildStrm->SetTargetMessage ( pNewMessage );
// Initialize control variables.
}
eState = INETMSG_EOL_BEGIN;
status = INetMessageIOStream::PutMsgLine(
pOldPos, pChar - pOldPos + 1 );
if( status != INETSTREAM_STATUS_OK )
return status;
}
}
}
if( pOldPos < pChar )
{
SvMemoryStream* pNewStream = new SvMemoryStream;
pNewStream->Write( pOldPos, pChar - pOldPos );
SvMemoryStream* pTmp = pMsgBuffer;
pMsgBuffer = pNewStream;
delete pTmp;
}
else
{
pMsgBuffer->Seek( 0L );
pMsgBuffer->SetStreamSize( 0 );
}
return INETSTREAM_STATUS_OK;
}
}
else
{
/*
* Single part message.
* Remove any ContentTransferEncoding.
*/
if (pMsg->GetContentType().Len() == 0)
{
String aDefaultCT;
pMsg->GetDefaultContentType (aDefaultCT);
pMsg->SetContentType (aDefaultCT);
}
if (eEncoding == INETMSG_ENCODING_BINARY)
{
String aEncoding (pMsg->GetContentTransferEncoding());
if (aEncoding.CompareIgnoreCaseToAscii (
"base64", 6) == COMPARE_EQUAL)
eEncoding = INETMSG_ENCODING_BASE64;
else if (aEncoding.CompareIgnoreCaseToAscii (
"quoted-printable", 16) == COMPARE_EQUAL)
eEncoding = INETMSG_ENCODING_QUOTED;
else
eEncoding = INETMSG_ENCODING_7BIT;
}
if (eEncoding == INETMSG_ENCODING_7BIT)
{
// No decoding necessary.
return INetMessageIOStream::PutMsgLine (pData, nSize);
}
else
{
if (pDecodeStrm == NULL)
{
if (eEncoding == INETMSG_ENCODING_QUOTED)
pDecodeStrm = new INetMessageDecodeQPStream_Impl;
else
pDecodeStrm = new INetMessageDecode64Stream_Impl;
pDecodeStrm->SetTargetMessage (pMsg);
}
return pDecodeStrm->Write (pData, nSize);
}
}
}
}