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

Generated by: LCOV version 1.11