LCOV - code coverage report
Current view: top level - libreoffice/tools/source/inet - inetstrm.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 609 0.0 %
Date: 2012-12-27 Functions: 0 44 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <comphelper/string.hxx>
      21             : #include <sal/types.h>
      22             : #include <rtl/strbuf.hxx>
      23             : #include <tools/cachestr.hxx>
      24             : #include <tools/inetmsg.hxx>
      25             : #include <tools/inetstrm.hxx>
      26             : 
      27             : #include <ctype.h> // toupper
      28             : 
      29           0 : inline sal_Bool SAL_CALL ascii_isWhitespace( sal_Unicode ch )
      30             : {
      31           0 :     return ((ch <= 0x20) && ch);
      32             : }
      33             : 
      34             : #define CONSTASCII_STRINGPARAM(a) (a), RTL_TEXTENCODING_ASCII_US
      35             : 
      36             : /** Quoted-Printable Encoding */
      37             : class INetMessageEncodeQPStream_Impl : public INetMessageIStream
      38             : {
      39             :     SvStream               *pMsgStrm;
      40             : 
      41             :     sal_uIntPtr             nMsgBufSiz;
      42             :     sal_Char               *pMsgBuffer;
      43             :     sal_Char               *pMsgRead;
      44             :     sal_Char               *pMsgWrite;
      45             : 
      46             :     sal_uIntPtr             nTokBufSiz;
      47             :     sal_Char               *pTokBuffer;
      48             :     sal_Char               *pTokRead;
      49             :     sal_Char               *pTokWrite;
      50             : 
      51             :     INetMessageStreamState  eState;
      52             :     sal_Bool                bDone;
      53             : 
      54             :     virtual int GetMsgLine (sal_Char *pData, sal_uIntPtr nSize);
      55             : 
      56             : public:
      57             :     INetMessageEncodeQPStream_Impl (sal_uIntPtr nMsgBufferSize = 1024);
      58             :     virtual ~INetMessageEncodeQPStream_Impl (void);
      59             : };
      60             : 
      61             : /** Quoted-Printable Decoding */
      62             : class INetMessageDecodeQPStream_Impl : public INetMessageOStream
      63             : {
      64             :     INetMessageStreamState  eState;
      65             :     SvMemoryStream         *pMsgBuffer;
      66             : 
      67             :     sal_uIntPtr             nTokBufLen;
      68             :     sal_Char                pTokBuffer[4];
      69             : 
      70             :     virtual int PutMsgLine (const sal_Char *pData, sal_uIntPtr nSize);
      71             : 
      72             : public:
      73             :     INetMessageDecodeQPStream_Impl (void);
      74             :     virtual ~INetMessageDecodeQPStream_Impl (void);
      75             : };
      76             : 
      77             : /** Base64 Encoding */
      78             : class INetMessageEncode64Stream_Impl : public INetMessageIStream
      79             : {
      80             :     SvStream    *pMsgStrm;
      81             : 
      82             :     sal_uIntPtr  nMsgBufSiz;
      83             :     sal_uInt8   *pMsgBuffer;
      84             :     sal_uInt8   *pMsgRead;
      85             :     sal_uInt8   *pMsgWrite;
      86             : 
      87             :     sal_uIntPtr  nTokBufSiz;
      88             :     sal_Char    *pTokBuffer;
      89             :     sal_Char    *pTokRead;
      90             :     sal_Char    *pTokWrite;
      91             : 
      92             :     sal_Bool     bDone;
      93             : 
      94             :     virtual int GetMsgLine (sal_Char *pData, sal_uIntPtr nSize);
      95             : 
      96             : public:
      97             :     INetMessageEncode64Stream_Impl (sal_uIntPtr nMsgBufferSize = 2048);
      98             :     virtual ~INetMessageEncode64Stream_Impl (void);
      99             : };
     100             : 
     101             : /** Base64 Decoding */
     102             : class INetMessageDecode64Stream_Impl : public INetMessageOStream
     103             : {
     104             :     INetMessageStreamState  eState;
     105             : 
     106             :     sal_uIntPtr             nMsgBufSiz;
     107             :     sal_Char               *pMsgBuffer;
     108             :     sal_Char               *pMsgRead;
     109             :     sal_Char               *pMsgWrite;
     110             : 
     111             :     virtual int PutMsgLine (const sal_Char *pData, sal_uIntPtr nSize);
     112             : 
     113             : public:
     114             :     INetMessageDecode64Stream_Impl (sal_uIntPtr nMsgBufferSize = 128);
     115             :     virtual ~INetMessageDecode64Stream_Impl (void);
     116             : };
     117             : 
     118             : // INetIStream
     119             : 
     120           0 : INetIStream::INetIStream ()
     121             : {
     122           0 : }
     123             : 
     124           0 : INetIStream::~INetIStream (void)
     125             : {
     126           0 : }
     127             : 
     128           0 : int INetIStream::Read (sal_Char *pData, sal_uIntPtr nSize)
     129             : {
     130           0 :     return GetData (pData, nSize);
     131             : }
     132             : 
     133             : // INetOStream
     134             : 
     135           0 : INetOStream::INetOStream ()
     136             : {
     137           0 : }
     138             : 
     139           0 : INetOStream::~INetOStream (void)
     140             : {
     141           0 : }
     142             : 
     143           0 : int INetOStream::Write (const sal_Char *pData, sal_uIntPtr nSize)
     144             : {
     145           0 :     return PutData (pData, nSize);
     146             : }
     147             : 
     148             : // INetMessageIStream
     149             : 
     150           0 : INetMessageIStream::INetMessageIStream (sal_uIntPtr nBufferSize)
     151             :     : pSourceMsg       (NULL),
     152             :       bHeaderGenerated (sal_False),
     153             :       nBufSiz          (nBufferSize),
     154             :       pMsgStrm         (NULL),
     155           0 :       pMsgBuffer       (new SvMemoryStream)
     156             : {
     157           0 :     pMsgBuffer->SetStreamCharSet (RTL_TEXTENCODING_ASCII_US);
     158           0 :     pBuffer = new sal_Char[nBufSiz];
     159           0 :     pRead = pWrite = pBuffer;
     160           0 : }
     161             : 
     162           0 : INetMessageIStream::~INetMessageIStream (void)
     163             : {
     164           0 :     delete [] pBuffer;
     165           0 :     delete pMsgBuffer;
     166           0 :     delete pMsgStrm;
     167           0 : }
     168             : 
     169           0 : int INetMessageIStream::GetData (sal_Char *pData, sal_uIntPtr nSize)
     170             : {
     171           0 :     if (pSourceMsg == NULL) return INETSTREAM_STATUS_ERROR;
     172             : 
     173           0 :     sal_Char *pWBuf = pData;
     174           0 :     sal_Char *pWEnd = pData + nSize;
     175             : 
     176           0 :     while (pWBuf < pWEnd)
     177             :     {
     178             :         // Caller's buffer not yet filled.
     179           0 :         sal_uIntPtr n = pRead - pWrite;
     180           0 :         if (n > 0)
     181             :         {
     182             :             // Bytes still in buffer.
     183           0 :             sal_uIntPtr m = pWEnd - pWBuf;
     184           0 :             if (m < n) n = m;
     185           0 :             for (sal_uIntPtr i = 0; i < n; i++) *pWBuf++ = *pWrite++;
     186             :         }
     187             :         else
     188             :         {
     189             :             // Buffer empty. Reset to <Begin-of-Buffer>.
     190           0 :             pRead = pWrite = pBuffer;
     191             : 
     192             :             // Read next message line.
     193           0 :             int nRead = GetMsgLine (pBuffer, nBufSiz);
     194           0 :             if (nRead > 0)
     195             :             {
     196             :                 // Set read pointer.
     197           0 :                 pRead = pBuffer + nRead;
     198             :             }
     199             :             else
     200             :             {
     201           0 :                 if (!bHeaderGenerated)
     202             :                 {
     203             :                     // Header generated. Insert empty line.
     204           0 :                     bHeaderGenerated = sal_True;
     205           0 :                     *pRead++ = '\r';
     206           0 :                     *pRead++ = '\n';
     207             :                 }
     208             :                 else
     209             :                 {
     210             :                     // Body generated.
     211           0 :                     return (pWBuf - pData);
     212             :                 }
     213             :             }
     214             :         }
     215             :     }
     216           0 :     return (pWBuf - pData);
     217             : }
     218             : 
     219           0 : int INetMessageIStream::GetMsgLine (sal_Char *pData, sal_uIntPtr nSize)
     220             : {
     221           0 :     if (pSourceMsg == NULL) return INETSTREAM_STATUS_ERROR;
     222             : 
     223           0 :     sal_Char *pWBuf = pData;
     224           0 :     sal_Char *pWEnd = pData + nSize;
     225             : 
     226           0 :     if (!bHeaderGenerated)
     227             :     {
     228             :         sal_uIntPtr i, n;
     229             : 
     230           0 :         if (pMsgBuffer->Tell() == 0)
     231             :         {
     232             :             // Insert formatted header into buffer.
     233           0 :             n = pSourceMsg->GetHeaderCount();
     234           0 :             for (i = 0; i < n; i++)
     235             :             {
     236           0 :                 INetMessageHeader aHeader (pSourceMsg->GetHeaderField(i));
     237           0 :                 if (aHeader.GetValue().getLength())
     238             :                 {
     239             :                     // NYI: Folding long lines.
     240           0 :                     *pMsgBuffer << aHeader.GetName().getStr();
     241           0 :                     *pMsgBuffer << ": ";
     242           0 :                     *pMsgBuffer << aHeader.GetValue().getStr();
     243           0 :                     *pMsgBuffer << "\r\n";
     244             :                 }
     245           0 :             }
     246             : 
     247           0 :             pMsgWrite = (sal_Char *)(pMsgBuffer->GetData());
     248           0 :             pMsgRead  = pMsgWrite + pMsgBuffer->Tell();
     249             :         }
     250             : 
     251           0 :         n = pMsgRead - pMsgWrite;
     252           0 :         if (n > 0)
     253             :         {
     254             :             // Move to caller.
     255           0 :             if (nSize < n) n = nSize;
     256           0 :             for (i = 0; i < n; i++) *pWBuf++ = *pMsgWrite++;
     257             :         }
     258             :         else
     259             :         {
     260             :             // Reset buffer.
     261           0 :             pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
     262             :         }
     263             :     }
     264             :     else
     265             :     {
     266           0 :         if (pSourceMsg->GetDocumentLB())
     267             :         {
     268           0 :             if (pMsgStrm == NULL)
     269           0 :                 pMsgStrm = new SvStream (pSourceMsg->GetDocumentLB());
     270             : 
     271           0 :             sal_uIntPtr nRead = pMsgStrm->Read (pWBuf, (pWEnd - pWBuf));
     272           0 :             pWBuf += nRead;
     273             :         }
     274             :     }
     275           0 :     return (pWBuf - pData);
     276             : }
     277             : 
     278             : // INetMessageOStream
     279             : 
     280           0 : INetMessageOStream::INetMessageOStream (void)
     281             :     : pTargetMsg    (NULL),
     282             :       bHeaderParsed (sal_False),
     283             :       eOState       (INETMSG_EOL_BEGIN),
     284           0 :       pMsgBuffer    (new SvMemoryStream)
     285             : {
     286           0 : }
     287             : 
     288           0 : INetMessageOStream::~INetMessageOStream (void)
     289             : {
     290           0 :     if (pMsgBuffer->Tell() > 0)
     291           0 :         PutMsgLine ((const sal_Char *) pMsgBuffer->GetData(), pMsgBuffer->Tell());
     292           0 :     delete pMsgBuffer;
     293             : 
     294           0 :     if (pTargetMsg)
     295             :     {
     296             :         SvOpenLockBytes *pLB =
     297           0 :             PTR_CAST (SvOpenLockBytes, pTargetMsg->GetDocumentLB());
     298           0 :         if (pLB)
     299             :         {
     300           0 :             pLB->Flush();
     301           0 :             pLB->Terminate();
     302             :         }
     303             :     }
     304           0 : }
     305             : 
     306             : /// Simple Field Parsing (RFC822, Appendix B)
     307           0 : int INetMessageOStream::PutData (const sal_Char *pData, sal_uIntPtr nSize)
     308             : {
     309           0 :     if (pTargetMsg == NULL) return INETSTREAM_STATUS_ERROR;
     310             : 
     311           0 :     const sal_Char *pStop = (pData + nSize);
     312             : 
     313           0 :     while (!bHeaderParsed && (pData < pStop))
     314             :     {
     315           0 :         if (eOState == INETMSG_EOL_BEGIN)
     316             :         {
     317           0 :             if ((*pData == '\r') || (*pData == '\n'))
     318             :             {
     319             :                 /*
     320             :                  * Empty Line. Separates header fields from message body.
     321             :                  * Skip this and any 2nd line break character (if any).
     322             :                  */
     323           0 :                 pData++;
     324           0 :                 if ((pData < pStop) && ((*pData == '\r') || (*pData == '\n')))
     325           0 :                     pData++;
     326             : 
     327             :                 // Emit any buffered last header field.
     328           0 :                 if (pMsgBuffer->Tell() > 0)
     329             :                 {
     330           0 :                     *pMsgBuffer << '\0';
     331             :                     int status = PutMsgLine (
     332           0 :                         (const sal_Char *) pMsgBuffer->GetData(),
     333           0 :                         pMsgBuffer->Tell());
     334           0 :                     if (status != INETSTREAM_STATUS_OK) return status;
     335             :                 }
     336             : 
     337             :                 // Reset to begin.
     338           0 :                 eOState = INETMSG_EOL_BEGIN;
     339           0 :                 pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
     340             : 
     341             :                 // Mark header parsed.
     342           0 :                 bHeaderParsed = sal_True;
     343             :             }
     344           0 :             else if ((*pData == ' ') || (*pData == '\t'))
     345             :             {
     346             :                 // Continuation line. Unfold multi-line field-body.
     347           0 :                 *pMsgBuffer << ' ';
     348           0 :                 pData++;
     349             :             }
     350             :             else
     351             :             {
     352             :                 // Begin of new header field.
     353           0 :                 if (pMsgBuffer->Tell() > 0)
     354             :                 {
     355             :                     // Emit buffered header field now.
     356           0 :                     *pMsgBuffer << '\0';
     357             :                     int status = PutMsgLine (
     358           0 :                         (const sal_Char *) pMsgBuffer->GetData(),
     359           0 :                         pMsgBuffer->Tell());
     360           0 :                     if (status != INETSTREAM_STATUS_OK) return status;
     361             :                 }
     362             : 
     363             :                 // Reset to begin of buffer.
     364           0 :                 pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
     365             : 
     366             :                 // Insert current character into buffer.
     367           0 :                 *pMsgBuffer << *pData++;
     368             :             }
     369             : 
     370             :             // Search for next line break character.
     371           0 :             if (!bHeaderParsed) eOState = INETMSG_EOL_SCR;
     372             :         }
     373           0 :         else if (eOState == INETMSG_EOL_FCR)
     374             :         {
     375             :             // Skip line break character.
     376           0 :             pData++;
     377             : 
     378             :             // Mark begin of line.
     379           0 :             eOState = INETMSG_EOL_BEGIN;
     380             :         }
     381           0 :         else if ((*pData == '\r') || (*pData == '\n'))
     382             :         {
     383           0 :             if (*pData == '\r') pData++;
     384           0 :             eOState = INETMSG_EOL_FCR;
     385             :         }
     386           0 :         else if (ascii_isWhitespace (*pData & 0x7f))
     387             :         {
     388             :             // Any <LWS> is folded into a single <SP> character.
     389           0 :             sal_Char c = *((const sal_Char *) pMsgBuffer->GetData() + pMsgBuffer->Tell() - 1);
     390           0 :             if (!ascii_isWhitespace (c & 0x7f)) *pMsgBuffer << ' ';
     391             : 
     392             :             // Skip over this <LWS> character.
     393           0 :             pData++;
     394             :         }
     395             :         else
     396             :         {
     397             :             // Any other character is inserted into line buffer.
     398           0 :             *pMsgBuffer << *pData++;
     399             :         }
     400             :     }
     401             : 
     402           0 :     if (bHeaderParsed && (pData < pStop))
     403             :     {
     404             :         // Put message body down-stream.
     405           0 :         return PutMsgLine (pData, (pStop - pData));
     406             :     }
     407             : 
     408           0 :     return INETSTREAM_STATUS_OK;
     409             : }
     410             : 
     411           0 : int INetMessageOStream::PutMsgLine (const sal_Char *pData, sal_uIntPtr nSize)
     412             : {
     413             :     // Check for message container.
     414           0 :     if (pTargetMsg == NULL) return INETSTREAM_STATUS_ERROR;
     415             : 
     416             :     // Check for header or body.
     417           0 :     if (!IsHeaderParsed())
     418             :     {
     419           0 :         rtl::OString aField(pData);
     420           0 :         sal_Int32 nPos = aField.indexOf(':');
     421           0 :         if (nPos != -1)
     422             :         {
     423             :             rtl::OString aName(
     424           0 :                 aField.copy(0, nPos));
     425             :             rtl::OString aValue(
     426           0 :                 aField.copy(nPos + 1, aField.getLength() - nPos + 1));
     427           0 :             aValue = comphelper::string::stripStart(aValue, ' ');
     428             : 
     429             :             pTargetMsg->SetHeaderField (
     430           0 :                 INetMessageHeader (aName, aValue));
     431           0 :         }
     432             :     }
     433             :     else
     434             :     {
     435             :         SvOpenLockBytes *pLB =
     436           0 :             PTR_CAST(SvOpenLockBytes, pTargetMsg->GetDocumentLB());
     437           0 :         if (pLB == NULL)
     438           0 :             return INETSTREAM_STATUS_WOULDBLOCK;
     439             : 
     440           0 :         sal_Size nDocSiz = pTargetMsg->GetDocumentSize();
     441           0 :         sal_Size nWrite  = 0;
     442             : 
     443           0 :         pLB->FillAppend ((sal_Char *)pData, nSize, &nWrite);
     444           0 :         pTargetMsg->SetDocumentSize (nDocSiz + nWrite);
     445             : 
     446           0 :         if (nWrite < nSize) return INETSTREAM_STATUS_ERROR;
     447             :     }
     448           0 :     return INETSTREAM_STATUS_OK;
     449             : }
     450             : 
     451             : // INetMessageIOStream
     452             : 
     453           0 : INetMessageIOStream::INetMessageIOStream (sal_uIntPtr nBufferSize)
     454             :     : INetMessageIStream (nBufferSize),
     455           0 :       INetMessageOStream ()
     456             : {
     457           0 : }
     458             : 
     459           0 : INetMessageIOStream::~INetMessageIOStream (void)
     460             : {
     461           0 : }
     462             : 
     463             : // INetMessageEncodeQPStream_Impl
     464             : 
     465             : static const sal_Char hex2pr[16] = {
     466             :     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
     467             :     'A', 'B', 'C', 'D', 'E', 'F'
     468             : };
     469             : 
     470             : static const sal_Char ebcdic[] = {
     471             :     '!', '"', '#', '$', '@', '[', '\\', ']', '^', '`', '{', '|', '}', '~'
     472             : };
     473             : 
     474           0 : INetMessageEncodeQPStream_Impl::INetMessageEncodeQPStream_Impl( sal_uIntPtr nMsgBufferSize)
     475             :     : INetMessageIStream (),
     476             :       pMsgStrm   (NULL),
     477             :       nMsgBufSiz (nMsgBufferSize),
     478             :       nTokBufSiz (80),
     479             :       eState     (INETMSG_EOL_SCR),
     480           0 :       bDone      (sal_False)
     481             : {
     482           0 :     GenerateHeader (sal_False);
     483             : 
     484           0 :     pMsgBuffer = new sal_Char[nMsgBufSiz];
     485           0 :     pMsgRead = pMsgWrite = pMsgBuffer;
     486             : 
     487           0 :     pTokBuffer = new sal_Char[nTokBufSiz];
     488           0 :     pTokRead = pTokWrite = pTokBuffer;
     489           0 : }
     490             : 
     491           0 : INetMessageEncodeQPStream_Impl::~INetMessageEncodeQPStream_Impl (void)
     492             : {
     493           0 :     delete pMsgStrm;
     494           0 :     delete [] pMsgBuffer;
     495           0 :     delete [] pTokBuffer;
     496           0 : }
     497             : 
     498           0 : int INetMessageEncodeQPStream_Impl::GetMsgLine (sal_Char *pData, sal_uIntPtr nSize)
     499             : {
     500           0 :     INetMessage *pMsg = GetSourceMessage ();
     501           0 :     if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
     502             : 
     503           0 :     if (pMsg->GetDocumentLB() == NULL) return 0;
     504           0 :     if (pMsgStrm == NULL) pMsgStrm = new SvStream (pMsg->GetDocumentLB());
     505             : 
     506           0 :     sal_Char *pWBuf = pData;
     507           0 :     while (pWBuf < (pData + nSize))
     508             :     {
     509             :         // Caller's buffer not yet filled.
     510           0 :         if ((pMsgRead - pMsgWrite) > 0)
     511             :         {
     512             :             // Bytes still in message buffer.
     513           0 :             if ((eState != INETMSG_EOL_BEGIN) &&
     514             :                 ((pTokRead - pTokBuffer) < 72))
     515             :             {
     516             :                 // Token buffer not yet filled.
     517           0 :                 if (eState == INETMSG_EOL_FCR)
     518             :                 {
     519           0 :                     eState = INETMSG_EOL_BEGIN;
     520           0 :                     if (*pMsgWrite != '\n')
     521             :                     {
     522             :                         // Convert orphant <CR> into <CR><LF> sequence.
     523           0 :                         *pTokRead++ = '\n';
     524             :                     }
     525           0 :                     *pTokRead++ = *pMsgWrite++;
     526             :                 }
     527           0 :                 else if ((*pMsgWrite == ' ') || (*pMsgWrite == '\t'))
     528             :                 {
     529           0 :                     eState = INETMSG_EOL_FSP;
     530           0 :                     *pTokRead++ = *pMsgWrite++;
     531             :                 }
     532           0 :                 else if (*pMsgWrite == '\r')
     533             :                 {
     534             :                     // Found <CR>.
     535           0 :                     if (eState == INETMSG_EOL_FSP)
     536             :                     {
     537             :                         // Encode last (trailing space) character.
     538           0 :                         sal_uInt8 c = (sal_uInt8)(*(--pTokRead));
     539           0 :                         *pTokRead++ = '=';
     540           0 :                         *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
     541           0 :                         *pTokRead++ = hex2pr[((c & 0x0f)     )];
     542             :                     }
     543           0 :                     eState = INETMSG_EOL_FCR;
     544           0 :                     *pTokRead++ = *pMsgWrite++;
     545             :                 }
     546           0 :                 else if (*pMsgWrite == '\n')
     547             :                 {
     548             :                     // Found <LF> only.
     549           0 :                     if (eState == INETMSG_EOL_FSP)
     550             :                     {
     551             :                         // Encode last (trailing space) character.
     552           0 :                         sal_uInt8 c = (sal_uInt8)(*(--pTokRead));
     553           0 :                         *pTokRead++ = '=';
     554           0 :                         *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
     555           0 :                         *pTokRead++ = hex2pr[((c & 0x0f)     )];
     556             :                     }
     557           0 :                     eState = INETMSG_EOL_BEGIN;
     558             : 
     559             :                     // Convert orphant <LF> into <CR><LF> sequence.
     560           0 :                     *pTokRead++ = '\r';
     561           0 :                     *pTokRead++ = *pMsgWrite++;
     562             :                 }
     563           0 :                 else if (*pMsgWrite == '=')
     564             :                 {
     565             :                     // Escape character itself MUST be encoded, of course.
     566           0 :                     sal_uInt8 c = (sal_uInt8)(*pMsgWrite++);
     567           0 :                     *pTokRead++ = '=';
     568           0 :                     *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
     569           0 :                     *pTokRead++ = hex2pr[((c & 0x0f)     )];
     570             : 
     571           0 :                     eState = INETMSG_EOL_SCR;
     572             :                 }
     573           0 :                 else if (((sal_uInt8)(*pMsgWrite) > 0x20) &&
     574             :                          ((sal_uInt8)(*pMsgWrite) < 0x7f)    )
     575             :                 {
     576             :                     /*
     577             :                      * Some printable ASCII character.
     578             :                      * (Encode EBCDIC special characters (NYI)).
     579             :                      */
     580           0 :                     *pTokRead++ = *pMsgWrite++;
     581           0 :                     eState = INETMSG_EOL_SCR;
     582             :                 }
     583             :                 else
     584             :                 {
     585             :                     // Encode any other character.
     586           0 :                     sal_uInt8 c = (sal_uInt8)(*pMsgWrite++);
     587           0 :                     *pTokRead++ = '=';
     588           0 :                     *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
     589           0 :                     *pTokRead++ = hex2pr[((c & 0x0f)     )];
     590             : 
     591           0 :                     eState = INETMSG_EOL_SCR;
     592           0 :                 }
     593             :             }
     594             :             else
     595             :             {
     596             :                 // Check for maximum line length.
     597           0 :                 if (eState != INETMSG_EOL_BEGIN)
     598             :                 {
     599             :                     // Insert soft line break.
     600           0 :                     *pTokRead++ = '=';
     601           0 :                     *pTokRead++ = '\r';
     602           0 :                     *pTokRead++ = '\n';
     603             : 
     604           0 :                     eState = INETMSG_EOL_BEGIN;
     605             :                 }
     606             : 
     607             :                 // Copy to caller's buffer.
     608           0 :                 if ((pTokRead - pTokWrite) > 0)
     609             :                 {
     610             :                     // Bytes still in token buffer.
     611           0 :                     *pWBuf++ = *pTokWrite++;
     612             :                 }
     613             :                 else
     614             :                 {
     615             :                     // Token buffer empty. Reset to <Begin-of-Buffer>.
     616           0 :                     pTokRead = pTokWrite = pTokBuffer;
     617           0 :                     eState = INETMSG_EOL_SCR;
     618             :                 }
     619             :             }
     620             :         }
     621             :         else
     622             :         {
     623             :             // Message buffer empty. Reset to <Begin-of-Buffer>.
     624           0 :             pMsgRead = pMsgWrite = pMsgBuffer;
     625             : 
     626             :             // Read next message block.
     627           0 :             sal_uIntPtr nRead = pMsgStrm->Read (pMsgBuffer, nMsgBufSiz);
     628           0 :             if (nRead > 0)
     629             :             {
     630             :                 // Set read pointer.
     631           0 :                 pMsgRead = (pMsgBuffer + nRead);
     632             :             }
     633             :             else
     634             :             {
     635             :                 // Nothing more ro read.
     636           0 :                 if (!bDone)
     637             :                 {
     638             :                     // Append final <CR><LF> and mark we're done.
     639           0 :                     *pTokRead++ = '\r';
     640           0 :                     *pTokRead++ = '\n';
     641             : 
     642           0 :                     bDone = sal_True;
     643             :                 }
     644             :                 else
     645             :                 {
     646             :                     // Already done all encoding.
     647           0 :                     if ((pTokRead - pTokWrite) > 0)
     648             :                     {
     649             :                         // Bytes still in token buffer.
     650           0 :                         *pWBuf++ = *pTokWrite++;
     651             :                     }
     652             :                     else
     653             :                     {
     654             :                         // Token buffer empty. Reset to <Begin-of-Buffer>.
     655           0 :                         pTokRead = pTokWrite = pTokBuffer;
     656             : 
     657             :                         // Return.
     658           0 :                         return (pWBuf - pData);
     659             :                     }
     660             :                 }
     661             :             }
     662             :         }
     663             :     }
     664           0 :     return (pWBuf - pData);
     665             : }
     666             : 
     667             : // INetMessageDecodeQPStream_Impl
     668             : 
     669             : static const sal_uInt8 pr2hex[128] = {
     670             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     671             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     672             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     673             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     674             : 
     675             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     676             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     677             :     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     678             :     0x08, 0x09, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     679             : 
     680             :     0x10, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
     681             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     682             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     683             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     684             : 
     685             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     686             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     687             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
     688             :     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
     689             : };
     690             : 
     691           0 : INetMessageDecodeQPStream_Impl::INetMessageDecodeQPStream_Impl (void)
     692             :     : INetMessageOStream (),
     693             :       eState     (INETMSG_EOL_BEGIN),
     694           0 :       pMsgBuffer (new SvMemoryStream),
     695           0 :       nTokBufLen (0)
     696             : {
     697           0 :     ParseHeader (sal_False);
     698           0 : }
     699             : 
     700           0 : INetMessageDecodeQPStream_Impl::~INetMessageDecodeQPStream_Impl (void)
     701             : {
     702           0 :     delete pMsgBuffer;
     703           0 : }
     704             : 
     705           0 : int INetMessageDecodeQPStream_Impl::PutMsgLine (
     706             :     const sal_Char *pData, sal_uIntPtr nSize)
     707             : {
     708           0 :     INetMessage *pMsg = GetTargetMessage();
     709           0 :     if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
     710             : 
     711           0 :     SvOpenLockBytes * pLB = PTR_CAST(SvOpenLockBytes, pMsg->GetDocumentLB());
     712           0 :     if (pLB == NULL) return INETSTREAM_STATUS_WOULDBLOCK;
     713             : 
     714           0 :     const sal_Char *pStop = pData + nSize;
     715           0 :     while (pData < pStop)
     716             :     {
     717           0 :         if (eState == INETMSG_EOL_FESC)
     718             :         {
     719           0 :             *(pTokBuffer + nTokBufLen++) = static_cast< char >(toupper(*pData));
     720           0 :             pData++;
     721           0 :             if (nTokBufLen == 2)
     722             :             {
     723           0 :                 if ((*pTokBuffer == '\r') || (*pTokBuffer == '\n'))
     724             :                 {
     725             :                     // Soft line break (=<CR><LF>). Emit buffer now.
     726           0 :                     eState = INETMSG_EOL_BEGIN;
     727             :                 }
     728             :                 else
     729             :                 {
     730             :                     // Decode token.
     731             :                     *pMsgBuffer << sal_uInt8 (
     732           0 :                         (pr2hex[(int)(pTokBuffer[0] & 0x7f)] << 4) |
     733           0 :                         (pr2hex[(int)(pTokBuffer[1] & 0x7f)] & 15)   );
     734             : 
     735             :                     // Search for next <CR>.
     736           0 :                     eState = INETMSG_EOL_SCR;
     737             :                 }
     738             : 
     739             :                 // Reset token buffer.
     740           0 :                 nTokBufLen = 0;
     741             :             }
     742             :         }
     743           0 :         else if (*pData == '=')
     744             :         {
     745             :             // Found escape character.
     746           0 :             pData++;
     747           0 :             eState = INETMSG_EOL_FESC;
     748             :         }
     749           0 :         else if (eState == INETMSG_EOL_FCR)
     750             :         {
     751           0 :             *pMsgBuffer << *pData++;
     752           0 :             eState = INETMSG_EOL_BEGIN;
     753             :         }
     754           0 :         else if (*pData == '\r')
     755             :         {
     756           0 :             *pMsgBuffer << *pData++;
     757           0 :             eState = INETMSG_EOL_FCR;
     758             :         }
     759             :         else
     760             :         {
     761           0 :             *pMsgBuffer << *pData++;
     762             :         }
     763             : 
     764           0 :         if (eState == INETMSG_EOL_BEGIN)
     765             :         {
     766           0 :             sal_Size nRead = pMsgBuffer->Tell();
     767           0 :             if (nRead > 0)
     768             :             {
     769             :                 // Emit buffer.
     770           0 :                 sal_Size nDocSiz = pMsg->GetDocumentSize();
     771           0 :                 sal_Size nWrite  = 0;
     772             : 
     773             :                 pLB->FillAppend (
     774           0 :                     (sal_Char *)(pMsgBuffer->GetData()), nRead, &nWrite);
     775           0 :                 pMsg->SetDocumentSize (nDocSiz + nWrite);
     776             : 
     777           0 :                 if (nWrite < nRead) return INETSTREAM_STATUS_ERROR;
     778             : 
     779           0 :                 pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
     780             :             }
     781           0 :             eState = INETMSG_EOL_SCR;
     782             :         }
     783             :     }
     784           0 :     return INETSTREAM_STATUS_OK;
     785             : }
     786             : 
     787             : // INetMessageEncode64Stream_Impl
     788             : 
     789             : static const sal_Char six2pr[64] = {
     790             :     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
     791             :     'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
     792             :     'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
     793             :     'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
     794             :     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
     795             : };
     796             : 
     797           0 : INetMessageEncode64Stream_Impl::INetMessageEncode64Stream_Impl (
     798             :     sal_uIntPtr nMsgBufferSize)
     799             :     : INetMessageIStream (),
     800             :       pMsgStrm   (NULL),
     801             :       nMsgBufSiz (nMsgBufferSize),
     802             :       nTokBufSiz (80),
     803           0 :       bDone      (sal_False)
     804             : {
     805           0 :     GenerateHeader (sal_False);
     806             : 
     807           0 :     pMsgBuffer = new sal_uInt8[nMsgBufSiz];
     808           0 :     pMsgRead = pMsgWrite = pMsgBuffer;
     809             : 
     810           0 :     pTokBuffer = new sal_Char[nTokBufSiz];
     811           0 :     pTokRead = pTokWrite = pTokBuffer;
     812           0 : }
     813             : 
     814           0 : INetMessageEncode64Stream_Impl::~INetMessageEncode64Stream_Impl (void)
     815             : {
     816           0 :     delete pMsgStrm;
     817           0 :     delete [] pMsgBuffer;
     818           0 :     delete [] pTokBuffer;
     819           0 : }
     820             : 
     821           0 : int INetMessageEncode64Stream_Impl::GetMsgLine (sal_Char *pData, sal_uIntPtr nSize)
     822             : {
     823           0 :     INetMessage *pMsg = GetSourceMessage ();
     824           0 :     if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
     825             : 
     826           0 :     if (pMsg->GetDocumentLB() == NULL) return 0;
     827           0 :     if (pMsgStrm == NULL) pMsgStrm = new SvStream (pMsg->GetDocumentLB());
     828             : 
     829           0 :     sal_Char *pWBuf = pData;
     830           0 :     while (pWBuf < (pData + nSize))
     831             :     {
     832             :         // Caller's buffer not yet filled.
     833           0 :         if ((pMsgRead - pMsgWrite) > 0)
     834             :         {
     835             :             // Bytes still in message buffer.
     836           0 :             if ((pTokRead - pTokBuffer) < 72)
     837             :             {
     838             :                 // Token buffer not yet filled.
     839           0 :                 switch ((pTokRead - pTokBuffer) % 4)
     840             :                 {
     841             :                     case 0:
     842           0 :                         *pTokRead++ = six2pr[(int)(*pMsgWrite >> 2)];
     843           0 :                         break;
     844             : 
     845             :                     case 1:
     846             :                         *pTokRead++ = six2pr[
     847             :                             (int)(((*pMsgWrite << 4) & 060) |
     848           0 :                                   (((*(pMsgWrite + 1)) >> 4) & 017))];
     849           0 :                         pMsgWrite++;
     850           0 :                         break;
     851             : 
     852             :                     case 2:
     853             :                         *pTokRead++ = six2pr[
     854             :                             (int)(((*pMsgWrite << 2) & 074) |
     855           0 :                                   (((*(pMsgWrite + 1)) >> 6) & 003))];
     856           0 :                         pMsgWrite++;
     857           0 :                         break;
     858             : 
     859             :                     default: // == case 3
     860           0 :                         *pTokRead++ = six2pr[(int)(*pMsgWrite & 077)];
     861           0 :                         pMsgWrite++;
     862           0 :                         break;
     863             :                 }
     864             :             }
     865           0 :             else if ((pTokRead - pTokBuffer) == 72)
     866             :             {
     867             :                 // Maximum line length. Append <CR><LF>.
     868           0 :                 *pTokRead++ = '\r';
     869           0 :                 *pTokRead++ = '\n';
     870             :             }
     871             :             else
     872             :             {
     873           0 :                 if ((pTokRead - pTokWrite) > 0)
     874             :                 {
     875             :                     // Bytes still in token buffer.
     876           0 :                     *pWBuf++ = *pTokWrite++;
     877             :                 }
     878             :                 else
     879             :                 {
     880             :                     // Token buffer empty. Reset to <Begin-of-Buffer>.
     881           0 :                     pTokRead = pTokWrite = pTokBuffer;
     882             :                 }
     883             :             }
     884             :         }
     885             :         else
     886             :         {
     887             :             // Message buffer empty. Reset to <Begin-of-Buffer>.
     888           0 :             pMsgRead = pMsgWrite = pMsgBuffer;
     889             : 
     890             :             // Read next message block.
     891           0 :             sal_uIntPtr nRead = pMsgStrm->Read (pMsgBuffer, nMsgBufSiz);
     892           0 :             if (nRead > 0)
     893             :             {
     894             :                 // Set read pointer.
     895           0 :                 pMsgRead = (pMsgBuffer + nRead);
     896             :             }
     897             :             else
     898             :             {
     899             :                 // Nothing more to read.
     900           0 :                 if (!bDone)
     901             :                 {
     902             :                     // Append pad character(s) and final <CR><LF>.
     903           0 :                     switch ((pTokRead - pTokBuffer) % 4)
     904             :                     {
     905             :                         case 2:
     906           0 :                             *pTokRead++ = '=';
     907             :                             // Fall through for 2nd pad character.
     908             : 
     909             :                         case 3:
     910           0 :                             *pTokRead++ = '=';
     911           0 :                             break;
     912             : 
     913             :                         default:
     914           0 :                             break;
     915             :                     }
     916           0 :                     *pTokRead++ = '\r';
     917           0 :                     *pTokRead++ = '\n';
     918             : 
     919             :                     // Mark we're done.
     920           0 :                     bDone = sal_True;
     921             :                 }
     922             :                 else
     923             :                 {
     924             :                     // Already done all encoding.
     925           0 :                     if ((pTokRead - pTokWrite) > 0)
     926             :                     {
     927             :                         // Bytes still in token buffer.
     928           0 :                         *pWBuf++ = *pTokWrite++;
     929             :                     }
     930             :                     else
     931             :                     {
     932             :                         // Token buffer empty. Reset to <Begin-of-Buffer>.
     933           0 :                         pTokRead = pTokWrite = pTokBuffer;
     934             : 
     935             :                         // Reset done flag, if everything has been done.
     936             :                         // if (pWBuf == pData) bDone = sal_False;
     937             : 
     938             :                         // Return.
     939           0 :                         return (pWBuf - pData);
     940             :                     }
     941             :                 }
     942             :             }
     943             :         }
     944             :     } // while (pWBuf < (pData + nSize))
     945           0 :     return (pWBuf - pData);
     946             : }
     947             : 
     948             : // INetMessageDecode64Stream_Impl
     949             : 
     950             : static const sal_uInt8 pr2six[256] = {
     951             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     952             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     953             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     954             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     955             : 
     956             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     957             :     0x40, 0x40, 0x40, 0x3E, 0x40, 0x40, 0x40, 0x3F,
     958             :     0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
     959             :     0x3C, 0x3D, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     960             : 
     961             :     0x40, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
     962             :     0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
     963             :     0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
     964             :     0x17, 0x18, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40,
     965             : 
     966             :     0x40, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
     967             :     0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
     968             :     0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
     969             :     0x31, 0x32, 0x33, 0x40, 0x40, 0x40, 0x40, 0x40,
     970             : 
     971             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     972             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     973             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     974             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     975             : 
     976             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     977             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     978             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     979             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     980             : 
     981             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     982             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     983             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     984             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     985             : 
     986             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     987             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     988             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
     989             :     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
     990             : };
     991             : 
     992           0 : INetMessageDecode64Stream_Impl::INetMessageDecode64Stream_Impl (
     993             :     sal_uIntPtr nMsgBufferSize)
     994             :     : INetMessageOStream (),
     995             :       eState     (INETMSG_EOL_SCR),
     996           0 :       nMsgBufSiz (nMsgBufferSize)
     997             : {
     998           0 :     ParseHeader (sal_False);
     999             : 
    1000           0 :     pMsgBuffer = new sal_Char[nMsgBufSiz];
    1001           0 :     pMsgRead = pMsgWrite = pMsgBuffer;
    1002           0 : }
    1003             : 
    1004           0 : INetMessageDecode64Stream_Impl::~INetMessageDecode64Stream_Impl (void)
    1005             : {
    1006           0 :     delete [] pMsgBuffer;
    1007           0 : }
    1008             : 
    1009           0 : int INetMessageDecode64Stream_Impl::PutMsgLine (
    1010             :     const sal_Char *pData, sal_uIntPtr nSize)
    1011             : {
    1012           0 :     INetMessage *pMsg = GetTargetMessage ();
    1013           0 :     if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
    1014             : 
    1015           0 :     SvOpenLockBytes * pLB = PTR_CAST(SvOpenLockBytes, pMsg->GetDocumentLB());
    1016           0 :     if (pLB == NULL) return INETSTREAM_STATUS_WOULDBLOCK;
    1017             : 
    1018           0 :     const sal_Char *pStop = (pData + nSize);
    1019           0 :     while (pData < pStop)
    1020             :     {
    1021           0 :         if (pr2six[(int)(*pData)] > 63)
    1022             :         {
    1023             :             /*
    1024             :              * Character not in base64 alphabet.
    1025             :              * Check for <End-of-Stream> or Junk.
    1026             :              */
    1027           0 :             if (*pData == '=')
    1028             :             {
    1029             :                 // Final pad character -> Done.
    1030           0 :                 sal_Size nDocSiz = pMsg->GetDocumentSize();
    1031           0 :                 sal_Size nRead   = pMsgWrite - pMsgBuffer;
    1032           0 :                 sal_Size nWrite  = 0;
    1033             : 
    1034           0 :                 pLB->FillAppend (pMsgBuffer, nRead, &nWrite);
    1035           0 :                 pMsg->SetDocumentSize (nDocSiz + nWrite);
    1036             : 
    1037           0 :                 if (nWrite < nRead)
    1038           0 :                     return INETSTREAM_STATUS_ERROR;
    1039             :                 else
    1040           0 :                     return INETSTREAM_STATUS_LOADED;
    1041             :             }
    1042           0 :             else if (eState == INETMSG_EOL_FCR)
    1043             :             {
    1044             :                 // Skip any line break character.
    1045           0 :                 if ((*pData == '\r') || (*pData == '\n')) pData++;
    1046             : 
    1047             :                 // Store decoded message buffer contents.
    1048           0 :                 sal_Size nDocSiz = pMsg->GetDocumentSize();
    1049           0 :                 sal_Size nRead   = pMsgWrite - pMsgBuffer;
    1050           0 :                 sal_Size nWrite  = 0;
    1051             : 
    1052           0 :                 pLB->FillAppend (pMsgBuffer, nRead, &nWrite);
    1053           0 :                 pMsg->SetDocumentSize (nDocSiz + nWrite);
    1054             : 
    1055           0 :                 if (nWrite < nRead) return INETSTREAM_STATUS_ERROR;
    1056             : 
    1057             :                 // Reset to <Begin-of-Buffer>.
    1058           0 :                 pMsgWrite = pMsgBuffer;
    1059           0 :                 eState = INETMSG_EOL_SCR;
    1060             :             }
    1061           0 :             else if ((*pData == '\r') || (*pData == '\n'))
    1062             :             {
    1063             :                 // Skip any line break character.
    1064           0 :                 pData++;
    1065           0 :                 eState = INETMSG_EOL_FCR;
    1066             :             }
    1067             :             else
    1068             :             {
    1069             :                 // Skip any junk character (may be transmission error).
    1070           0 :                 pData++;
    1071             :             }
    1072             :         }
    1073             :         else
    1074             :         {
    1075             :             // Decode any other character into message buffer.
    1076           0 :             switch ((pMsgRead - pMsgBuffer) % 4)
    1077             :             {
    1078             :                 case 0:
    1079           0 :                     *pMsgWrite    = (pr2six[(int)(*pData++)] << 2);
    1080           0 :                     pMsgRead++;
    1081           0 :                     break;
    1082             : 
    1083             :                 case 1:
    1084           0 :                     *pMsgWrite++ |= (pr2six[(int)(*pData  )] >> 4);
    1085           0 :                     *pMsgWrite    = (pr2six[(int)(*pData++)] << 4);
    1086           0 :                     pMsgRead++;
    1087           0 :                     break;
    1088             : 
    1089             :                 case 2:
    1090           0 :                     *pMsgWrite++ |= (pr2six[(int)(*pData  )] >> 2);
    1091           0 :                     *pMsgWrite    = (pr2six[(int)(*pData++)] << 6);
    1092           0 :                     pMsgRead++;
    1093           0 :                     break;
    1094             : 
    1095             :                 default: // == case 3
    1096           0 :                     *pMsgWrite++ |= (pr2six[(int)(*pData++)]);
    1097           0 :                     pMsgRead = pMsgBuffer;
    1098           0 :                     break;
    1099             :             } // switch ((pMsgRead - pMsgBuffer) % 4)
    1100             :         }
    1101             :     } // while (pData < pStop)
    1102           0 :     return INETSTREAM_STATUS_OK;
    1103             : }
    1104             : 
    1105             : // INetMIMEMessageStream
    1106             : 
    1107           0 : INetMIMEMessageStream::INetMIMEMessageStream (sal_uIntPtr nBufferSize)
    1108             :     : INetMessageIOStream (nBufferSize),
    1109             :       eState      (INETMSG_EOL_BEGIN),
    1110             :       nChildIndex (0),
    1111             :       pChildStrm  (NULL),
    1112             :       eEncoding   (INETMSG_ENCODING_BINARY),
    1113             :       pEncodeStrm (NULL),
    1114             :       pDecodeStrm (NULL),
    1115           0 :       pMsgBuffer  (NULL)
    1116             : {
    1117           0 : }
    1118             : 
    1119           0 : INetMIMEMessageStream::~INetMIMEMessageStream (void)
    1120             : {
    1121           0 :     delete pChildStrm;
    1122           0 :     delete pEncodeStrm;
    1123           0 :     delete pDecodeStrm;
    1124           0 :     delete pMsgBuffer;
    1125           0 : }
    1126             : 
    1127             : INetMessageEncoding
    1128           0 : INetMIMEMessageStream::GetMsgEncoding (const String& rContentType)
    1129             : {
    1130           0 :     if ((rContentType.CompareIgnoreCaseToAscii ("message"  , 7) == 0) ||
    1131           0 :         (rContentType.CompareIgnoreCaseToAscii ("multipart", 9) == 0)    )
    1132           0 :         return INETMSG_ENCODING_7BIT;
    1133             : 
    1134           0 :     if (rContentType.CompareIgnoreCaseToAscii ("text", 4) == 0)
    1135             :     {
    1136           0 :         if (rContentType.CompareIgnoreCaseToAscii ("text/plain", 10) == 0)
    1137             :         {
    1138           0 :             if (comphelper::string::getTokenCount(rContentType, '=') > 1)
    1139             :             {
    1140           0 :                 String aCharset (rContentType.GetToken (1, '='));
    1141           0 :                 aCharset = comphelper::string::stripStart(aCharset, ' ');
    1142           0 :                 aCharset = comphelper::string::stripStart(aCharset, '"');
    1143             : 
    1144           0 :                 if (aCharset.CompareIgnoreCaseToAscii ("us-ascii", 8) == 0)
    1145           0 :                     return INETMSG_ENCODING_7BIT;
    1146             :                 else
    1147           0 :                     return INETMSG_ENCODING_QUOTED;
    1148             :             }
    1149             :             else
    1150           0 :                 return INETMSG_ENCODING_7BIT;
    1151             :         }
    1152             :         else
    1153           0 :             return INETMSG_ENCODING_QUOTED;
    1154             :     }
    1155             : 
    1156           0 :     return INETMSG_ENCODING_BASE64;
    1157             : }
    1158             : 
    1159             : /// Message Generator
    1160           0 : int INetMIMEMessageStream::GetMsgLine (sal_Char *pData, sal_uIntPtr nSize)
    1161             : {
    1162             :     // Check for message container.
    1163           0 :     INetMIMEMessage *pMsg = GetSourceMessage();
    1164           0 :     if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
    1165             : 
    1166             :     // Check for header or body.
    1167           0 :     if (!IsHeaderGenerated())
    1168             :     {
    1169           0 :         if (eState == INETMSG_EOL_BEGIN)
    1170             :         {
    1171             :             // Prepare special header fields.
    1172           0 :             if (pMsg->GetParent())
    1173             :             {
    1174           0 :                 String aPCT (pMsg->GetParent()->GetContentType());
    1175           0 :                 if (aPCT.CompareIgnoreCaseToAscii ("message/rfc822", 14) == 0)
    1176             :                     pMsg->SetMIMEVersion (
    1177           0 :                         String(CONSTASCII_STRINGPARAM("1.0")));
    1178             :                 else
    1179           0 :                     pMsg->SetMIMEVersion (String());
    1180             :             }
    1181             :             else
    1182             :             {
    1183           0 :                 pMsg->SetMIMEVersion (String(CONSTASCII_STRINGPARAM("1.0")));
    1184             :             }
    1185             : 
    1186             :             // Check ContentType.
    1187           0 :             String aContentType (pMsg->GetContentType());
    1188           0 :             if (aContentType.Len())
    1189             :             {
    1190             :                 // Determine default Content-Type.
    1191           0 :                 UniString aDefaultType = pMsg->GetDefaultContentType();
    1192             : 
    1193           0 :                 if (aDefaultType.CompareIgnoreCaseToAscii (
    1194           0 :                     aContentType, aContentType.Len()) == 0)
    1195             :                 {
    1196             :                     // No need to specify default.
    1197           0 :                     pMsg->SetContentType (String());
    1198           0 :                 }
    1199             :             }
    1200             : 
    1201             :             // Check Encoding.
    1202           0 :             String aEncoding (pMsg->GetContentTransferEncoding());
    1203           0 :             if (aEncoding.Len())
    1204             :             {
    1205             :                 // Use given Encoding.
    1206           0 :                 if (aEncoding.CompareIgnoreCaseToAscii (
    1207           0 :                     "base64", 6) == 0)
    1208           0 :                     eEncoding = INETMSG_ENCODING_BASE64;
    1209           0 :                 else if (aEncoding.CompareIgnoreCaseToAscii (
    1210           0 :                     "quoted-printable", 16) == 0)
    1211           0 :                     eEncoding = INETMSG_ENCODING_QUOTED;
    1212             :                 else
    1213           0 :                     eEncoding = INETMSG_ENCODING_7BIT;
    1214             :             }
    1215             :             else
    1216             :             {
    1217             :                 // Use default Encoding for (given|default) Content-Type.
    1218           0 :                 if (aContentType.Len() == 0)
    1219             :                 {
    1220             :                     // Determine default Content-Type.
    1221           0 :                     aContentType = pMsg->GetDefaultContentType();
    1222             :                 }
    1223           0 :                 eEncoding = GetMsgEncoding (aContentType);
    1224             :             }
    1225             : 
    1226             :             // Set Content-Transfer-Encoding header.
    1227           0 :             if (eEncoding == INETMSG_ENCODING_BASE64)
    1228             :             {
    1229             :                 // Base64.
    1230             :                 pMsg->SetContentTransferEncoding (
    1231           0 :                     String(CONSTASCII_STRINGPARAM("base64")));
    1232             :             }
    1233           0 :             else if (eEncoding == INETMSG_ENCODING_QUOTED)
    1234             :             {
    1235             :                 // Quoted-Printable.
    1236             :                 pMsg->SetContentTransferEncoding (
    1237           0 :                     String(CONSTASCII_STRINGPARAM("quoted-printable")));
    1238             :             }
    1239             :             else
    1240             :             {
    1241             :                 // No need to specify default.
    1242           0 :                 pMsg->SetContentTransferEncoding (String());
    1243             :             }
    1244             : 
    1245             :             // Mark we're done.
    1246           0 :             eState = INETMSG_EOL_DONE;
    1247             :         }
    1248             : 
    1249             :         // Generate the message header.
    1250           0 :         int nRead = INetMessageIOStream::GetMsgLine (pData, nSize);
    1251           0 :         if (nRead <= 0)
    1252             :         {
    1253             :             // Reset state.
    1254           0 :             eState = INETMSG_EOL_BEGIN;
    1255             :         }
    1256           0 :         return nRead;
    1257             :     }
    1258             :     else
    1259             :     {
    1260             :         // Generate the message body.
    1261           0 :         if (pMsg->IsContainer())
    1262             :         {
    1263             :             // Encapsulated message body.
    1264           0 :             while (eState == INETMSG_EOL_BEGIN)
    1265             :             {
    1266           0 :                 if (pChildStrm == NULL)
    1267             :                 {
    1268           0 :                     INetMIMEMessage *pChild = pMsg->GetChild (nChildIndex);
    1269           0 :                     if (pChild)
    1270             :                     {
    1271             :                         // Increment child index.
    1272           0 :                         nChildIndex++;
    1273             : 
    1274             :                         // Create child stream.
    1275           0 :                         pChildStrm = new INetMIMEMessageStream;
    1276           0 :                         pChildStrm->SetSourceMessage (pChild);
    1277             : 
    1278           0 :                         if (pMsg->IsMultipart())
    1279             :                         {
    1280             :                             // Insert multipart delimiter.
    1281             :                             rtl::OStringBuffer aDelim(
    1282           0 :                                 RTL_CONSTASCII_STRINGPARAM("--"));
    1283           0 :                             aDelim.append(pMsg->GetMultipartBoundary());
    1284           0 :                             aDelim.append(RTL_CONSTASCII_STRINGPARAM("\r\n"));
    1285             : 
    1286           0 :                             memcpy(pData, aDelim.getStr(),
    1287           0 :                                 aDelim.getLength());
    1288           0 :                             return aDelim.getLength();
    1289             :                         }
    1290             :                     }
    1291             :                     else
    1292             :                     {
    1293             :                         // No more parts. Mark we're done.
    1294           0 :                         eState = INETMSG_EOL_DONE;
    1295           0 :                         nChildIndex = 0;
    1296             : 
    1297           0 :                         if (pMsg->IsMultipart())
    1298             :                         {
    1299             :                             // Insert close delimiter.
    1300             :                             rtl::OStringBuffer aDelim(
    1301           0 :                                 RTL_CONSTASCII_STRINGPARAM("--"));
    1302           0 :                             aDelim.append(pMsg->GetMultipartBoundary());
    1303           0 :                             aDelim.append(RTL_CONSTASCII_STRINGPARAM("--\r\n"));
    1304             : 
    1305           0 :                             memcpy (pData, aDelim.getStr(),
    1306           0 :                                 aDelim.getLength());
    1307           0 :                             return aDelim.getLength();
    1308             :                         }
    1309             :                     }
    1310             :                 }
    1311             :                 else
    1312             :                 {
    1313             :                     // Read current child stream.
    1314           0 :                     int nRead = pChildStrm->Read (pData, nSize);
    1315           0 :                     if (nRead > 0)
    1316             :                     {
    1317           0 :                         return nRead;
    1318             :                     }
    1319             :                     else
    1320             :                     {
    1321             :                         // Cleanup exhausted child stream.
    1322           0 :                         delete pChildStrm;
    1323           0 :                         pChildStrm = NULL;
    1324             :                     }
    1325             :                 }
    1326             :             }
    1327           0 :             return 0;
    1328             :         }
    1329             :         else
    1330             :         {
    1331             :             // Single part message body.
    1332           0 :             if (pMsg->GetDocumentLB() == NULL)
    1333             :             {
    1334             :                 // Empty message body.
    1335           0 :                 return 0;
    1336             :             }
    1337             :             else
    1338             :             {
    1339             :                 // Check whether message body needs to be encoded.
    1340           0 :                 if (eEncoding == INETMSG_ENCODING_7BIT)
    1341             :                 {
    1342             :                     // No Encoding.
    1343           0 :                     return INetMessageIOStream::GetMsgLine (pData, nSize);
    1344             :                 }
    1345             :                 else
    1346             :                 {
    1347             :                     // Apply appropriate Encoding.
    1348           0 :                     while (eState == INETMSG_EOL_BEGIN)
    1349             :                     {
    1350           0 :                         if (pEncodeStrm == NULL)
    1351             :                         {
    1352             :                             // Create encoder stream.
    1353           0 :                             if (eEncoding == INETMSG_ENCODING_QUOTED)
    1354             :                             {
    1355             :                                 // Quoted-Printable Encoding.
    1356             :                                 pEncodeStrm
    1357           0 :                                  = new INetMessageEncodeQPStream_Impl;
    1358             :                             }
    1359             :                             else
    1360             :                             {
    1361             :                                 // Base64 Encoding.
    1362             :                                 pEncodeStrm
    1363           0 :                                  = new INetMessageEncode64Stream_Impl;
    1364             :                             }
    1365           0 :                             pEncodeStrm->SetSourceMessage (pMsg);
    1366             :                         }
    1367             : 
    1368             :                         // Read encoded message.
    1369           0 :                         int nRead = pEncodeStrm->Read (pData, nSize);
    1370           0 :                         if (nRead > 0)
    1371             :                         {
    1372           0 :                             return nRead;
    1373             :                         }
    1374             :                         else
    1375             :                         {
    1376             :                             // Cleanup exhausted encoder stream.
    1377           0 :                             delete pEncodeStrm;
    1378           0 :                             pEncodeStrm = NULL;
    1379             : 
    1380             :                             // Mark we're done.
    1381           0 :                             eState = INETMSG_EOL_DONE;
    1382             :                         }
    1383             :                     }
    1384           0 :                     return 0;
    1385             :                 }
    1386             :             }
    1387             :         }
    1388             :     }
    1389             : }
    1390             : 
    1391             : /// Message Parser
    1392           0 : int INetMIMEMessageStream::PutMsgLine (const sal_Char *pData, sal_uIntPtr nSize)
    1393             : {
    1394             :     // Check for message container.
    1395           0 :     INetMIMEMessage *pMsg = GetTargetMessage();
    1396           0 :     if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
    1397             : 
    1398             :     // Check for header or body.
    1399           0 :     if (!IsHeaderParsed())
    1400             :     {
    1401             :         // Parse the message header.
    1402           0 :         int nRet = INetMessageIOStream::PutMsgLine (pData, nSize);
    1403           0 :         return nRet;
    1404             :     }
    1405             :     else
    1406             :     {
    1407           0 :         pMsg->SetHeaderParsed();
    1408             :         // Parse the message body.
    1409           0 :         if (pMsg->IsContainer())
    1410             :         {
    1411             : 
    1412             :             // Content-Transfer-Encoding MUST be "7bit" (RFC1521).
    1413           0 :             if (pMsg->IsMessage())
    1414             :             {
    1415           0 :                 if( !pChildStrm )
    1416             :                 {
    1417             :                     // Encapsulated message.
    1418           0 :                     INetMIMEMessage* pNewMessage = new INetMIMEMessage;
    1419             :                     pNewMessage->SetDocumentLB (
    1420           0 :                         new SvAsyncLockBytes(new SvCacheStream, sal_False));
    1421           0 :                     pMsg->AttachChild( *pNewMessage, sal_True );
    1422             : 
    1423             :                     // Encapsulated message body. Create message parser stream.
    1424           0 :                     pChildStrm = new INetMIMEMessageStream;
    1425           0 :                     pChildStrm->SetTargetMessage ( pNewMessage );
    1426             : 
    1427             :                     // Initialize control variables.
    1428           0 :                     eState = INETMSG_EOL_BEGIN;
    1429             :                 }
    1430           0 :                 if ( nSize > 0)
    1431             :                 {
    1432             :                     // Bytes still in buffer. Put message down-stream.
    1433           0 :                     int status = pChildStrm->Write( pData, nSize );
    1434           0 :                     if (status != INETSTREAM_STATUS_OK)
    1435           0 :                         return status;
    1436             :                 }
    1437             : 
    1438           0 :                 return INetMessageIOStream::PutMsgLine (pData, nSize);
    1439             :             }
    1440             :             else
    1441             :             {
    1442             : 
    1443             :                 // Multipart message body. Initialize multipart delimiters.
    1444             :                 // Multipart message.
    1445           0 :                 if (pMsg->GetMultipartBoundary().getLength() == 0)
    1446             :                 {
    1447             :                     // Determine boundary.
    1448             :                     rtl::OString aType(rtl::OUStringToOString(
    1449           0 :                         pMsg->GetContentType(), RTL_TEXTENCODING_ASCII_US));
    1450           0 :                     rtl::OString aLowerType(aType.toAsciiLowerCase());
    1451             : 
    1452             :                     sal_Int32 nPos = aLowerType.indexOfL(
    1453           0 :                         RTL_CONSTASCII_STRINGPARAM("boundary="));
    1454           0 :                     rtl::OString aBoundary(aType.copy(nPos + 9));
    1455             : 
    1456           0 :                     aBoundary = comphelper::string::strip(aBoundary, ' ');
    1457           0 :                     aBoundary = comphelper::string::strip(aBoundary, '"');
    1458             : 
    1459             :                     // Save boundary.
    1460           0 :                     pMsg->SetMultipartBoundary (aBoundary);
    1461             :                 }
    1462             : 
    1463           0 :                 rtl::OString aPlainDelim (pMsg->GetMultipartBoundary());
    1464             :                 rtl::OString aDelim = rtl::OStringBuffer(
    1465             :                     RTL_CONSTASCII_STRINGPARAM("--")).
    1466           0 :                     append(aPlainDelim).
    1467           0 :                     makeStringAndClear();
    1468             :                 rtl::OString aPlainClose = rtl::OStringBuffer(
    1469             :                     aPlainDelim).
    1470           0 :                     append(RTL_CONSTASCII_STRINGPARAM("--")).
    1471           0 :                     makeStringAndClear();
    1472             :                 rtl::OString aClose = rtl::OStringBuffer(
    1473             :                     aDelim).
    1474           0 :                     append(RTL_CONSTASCII_STRINGPARAM("--")).
    1475           0 :                     makeStringAndClear();
    1476             : 
    1477           0 :                 if (pMsgBuffer == NULL) pMsgBuffer = new SvMemoryStream;
    1478           0 :                 pMsgBuffer->Write (pData, nSize);
    1479           0 :                 sal_uIntPtr nBufSize = pMsgBuffer->Tell();
    1480             : 
    1481             :                 const sal_Char* pChar;
    1482             :                 const sal_Char* pOldPos;
    1483           0 :                 for( pOldPos = pChar = (const sal_Char *) pMsgBuffer->GetData(); nBufSize--;
    1484             :                      pChar++ )
    1485             :                 {
    1486             :                     int status;
    1487           0 :                     if( *pChar == '\r' || *pChar == '\n' )
    1488             :                     {
    1489           0 :                         if( aDelim.compareTo(pOldPos, aDelim.getLength())
    1490             :                             != -1 &&
    1491           0 :                             aClose.compareTo(pOldPos, aClose.getLength())
    1492             :                             != -1 &&
    1493           0 :                             aPlainDelim.compareTo(pOldPos, aPlainDelim.getLength())
    1494             :                             != -1 &&
    1495           0 :                             aPlainClose.compareTo(pOldPos, aPlainClose.getLength())
    1496             :                             != -1 )
    1497             :                         {
    1498           0 :                             if( nBufSize &&
    1499           0 :                                 ( pChar[1] == '\r' || pChar[1] == '\n' ) )
    1500           0 :                                 nBufSize--, pChar++;
    1501           0 :                             if( pChildStrm )
    1502             :                             {
    1503             :                                 status = pChildStrm->Write(
    1504           0 :                                     pOldPos, pChar - pOldPos + 1 );
    1505           0 :                                 if( status != INETSTREAM_STATUS_OK )
    1506           0 :                                     return status;
    1507             :                             }
    1508             :                             else {
    1509             :                                 SAL_WARN( "tools.stream", "Boundary not found." );
    1510             :                             }
    1511             :                             status = INetMessageIOStream::PutMsgLine(
    1512           0 :                                 pOldPos, pChar - pOldPos + 1 );
    1513           0 :                             if( status != INETSTREAM_STATUS_OK )
    1514           0 :                                 return status;
    1515           0 :                             pOldPos = pChar + 1;
    1516             :                         }
    1517             :                         else
    1518             :                         {
    1519           0 :                             if( nBufSize &&
    1520           0 :                                 ( pChar[1] == '\r' || pChar[1] == '\n' ) )
    1521           0 :                                 nBufSize--, pChar++;
    1522           0 :                             pOldPos = pChar + 1;
    1523           0 :                             DELETEZ( pChildStrm );
    1524             : 
    1525           0 :                             if (aClose.compareTo(pOldPos, aClose.getLength())
    1526             :                                 != -1 &&
    1527           0 :                                 aPlainClose.compareTo(pOldPos, aClose.getLength())
    1528             :                                 != -1 )
    1529             :                             {
    1530             :                                 // Encapsulated message.
    1531             :                                 INetMIMEMessage* pNewMessage =
    1532           0 :                                     new INetMIMEMessage;
    1533             :                                 pNewMessage->SetDocumentLB (
    1534             :                                     new SvAsyncLockBytes (
    1535           0 :                                         new SvCacheStream, sal_False));
    1536             : 
    1537           0 :                                 pMsg->AttachChild( *pNewMessage, sal_True );
    1538             : 
    1539             :                                 // Encapsulated message body. Create message parser stream.
    1540           0 :                                 pChildStrm = new INetMIMEMessageStream;
    1541           0 :                                 pChildStrm->SetTargetMessage ( pNewMessage );
    1542             : 
    1543             :                                 // Initialize control variables.
    1544             :                             }
    1545           0 :                             eState = INETMSG_EOL_BEGIN;
    1546             :                             status = INetMessageIOStream::PutMsgLine(
    1547           0 :                                 pOldPos, pChar - pOldPos + 1 );
    1548           0 :                             if( status != INETSTREAM_STATUS_OK )
    1549           0 :                                 return status;
    1550             :                         }
    1551             :                     }
    1552             :                 }
    1553           0 :                 if( pOldPos < pChar )
    1554             :                 {
    1555           0 :                     SvMemoryStream* pNewStream = new SvMemoryStream;
    1556           0 :                     pNewStream->Write( pOldPos, pChar - pOldPos );
    1557           0 :                     SvMemoryStream* pTmp = pMsgBuffer;
    1558           0 :                     pMsgBuffer = pNewStream;
    1559           0 :                     delete pTmp;
    1560             :                 }
    1561             :                 else
    1562             :                 {
    1563           0 :                     pMsgBuffer->Seek( 0L );
    1564           0 :                     pMsgBuffer->SetStreamSize( 0 );
    1565             :                 }
    1566           0 :                 return INETSTREAM_STATUS_OK;
    1567             :             }
    1568             :         }
    1569             :         else
    1570             :         {
    1571             :             /*
    1572             :              * Single part message.
    1573             :              * Remove any ContentTransferEncoding.
    1574             :              */
    1575           0 :             if (pMsg->GetContentType().isEmpty())
    1576             :             {
    1577           0 :                 pMsg->SetContentType(pMsg->GetDefaultContentType());
    1578             :             }
    1579             : 
    1580           0 :             if (eEncoding == INETMSG_ENCODING_BINARY)
    1581             :             {
    1582           0 :                 String aEncoding (pMsg->GetContentTransferEncoding());
    1583           0 :                 if (aEncoding.CompareIgnoreCaseToAscii (
    1584           0 :                     "base64", 6) == COMPARE_EQUAL)
    1585           0 :                     eEncoding = INETMSG_ENCODING_BASE64;
    1586           0 :                 else if (aEncoding.CompareIgnoreCaseToAscii (
    1587           0 :                     "quoted-printable", 16) == COMPARE_EQUAL)
    1588           0 :                     eEncoding = INETMSG_ENCODING_QUOTED;
    1589             :                 else
    1590           0 :                     eEncoding = INETMSG_ENCODING_7BIT;
    1591             :             }
    1592             : 
    1593           0 :             if (eEncoding == INETMSG_ENCODING_7BIT)
    1594             :             {
    1595             :                 // No decoding necessary.
    1596           0 :                 return INetMessageIOStream::PutMsgLine (pData, nSize);
    1597             :             }
    1598             :             else
    1599             :             {
    1600           0 :                 if (pDecodeStrm == NULL)
    1601             :                 {
    1602           0 :                     if (eEncoding == INETMSG_ENCODING_QUOTED)
    1603           0 :                         pDecodeStrm = new INetMessageDecodeQPStream_Impl;
    1604             :                     else
    1605           0 :                         pDecodeStrm = new INetMessageDecode64Stream_Impl;
    1606             : 
    1607           0 :                     pDecodeStrm->SetTargetMessage (pMsg);
    1608             :                 }
    1609           0 :                 return pDecodeStrm->Write (pData, nSize);
    1610             :             }
    1611             :         }
    1612             :     }
    1613             : }
    1614             : 
    1615             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10