LCOV - code coverage report
Current view: top level - tools/source/inet - inetstrm.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 609 0.0 %
Date: 2012-08-25 Functions: 0 44 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 797 0.0 %

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

Generated by: LCOV version 1.10