LCOV - code coverage report
Current view: top level - libreoffice/tools/source/inet - inetmime.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 122 1443 8.5 %
Date: 2012-12-27 Functions: 8 55 14.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <cstddef>
      21             : #include <limits>
      22             : 
      23             : #include <rtl/strbuf.hxx>
      24             : #include <rtl/tencinfo.h>
      25             : #include <tools/inetmime.hxx>
      26             : 
      27             : namespace unnamed_tools_inetmime {} using namespace unnamed_tools_inetmime;
      28             :     // unnamed namespaces don't work well yet
      29             : 
      30             : namespace unnamed_tools_inetmime {
      31             : 
      32             : class Charset
      33             : {
      34             :     rtl_TextEncoding m_eEncoding;
      35             :     const sal_uInt32 * m_pRanges;
      36             : 
      37             : public:
      38             :     inline Charset(rtl_TextEncoding eTheEncoding,
      39             :                    const sal_uInt32 * pTheRanges);
      40             : 
      41           0 :     rtl_TextEncoding getEncoding() const { return m_eEncoding; }
      42             : 
      43             :     bool contains(sal_uInt32 nChar) const;
      44             : };
      45             : 
      46           0 : inline Charset::Charset(rtl_TextEncoding eTheEncoding,
      47             :                         const sal_uInt32 * pTheRanges):
      48             :     m_eEncoding(eTheEncoding),
      49           0 :     m_pRanges(pTheRanges)
      50             : {
      51             :     DBG_ASSERT(m_pRanges, "Charset::Charset(): Bad ranges");
      52           0 : }
      53             : 
      54             : void appendISO88591(UniString & rText, sal_Char const * pBegin,
      55             :                     sal_Char const * pEnd);
      56             : 
      57             : }
      58             : 
      59             : class INetMIMECharsetList_Impl
      60             : {
      61             :     struct Node
      62             :     {
      63             :         Charset m_aCharset;
      64             :         bool m_bDisabled;
      65             :         Node * m_pNext;
      66             : 
      67             :         inline Node(const Charset & rTheCharset, bool bTheDisabled,
      68             :                     Node * pTheNext);
      69             :     };
      70             : 
      71             :     Node * m_pFirst;
      72             : 
      73             : public:
      74           0 :     INetMIMECharsetList_Impl(): m_pFirst(0) {}
      75             : 
      76             :     ~INetMIMECharsetList_Impl();
      77             : 
      78           0 :     void prepend(const Charset & rCharset)
      79           0 :     { m_pFirst = new Node(rCharset, false, m_pFirst); }
      80             : 
      81             :     void includes(sal_uInt32 nChar);
      82             : 
      83             :     rtl_TextEncoding getPreferredEncoding(rtl_TextEncoding eDefault
      84             :                                               = RTL_TEXTENCODING_DONTKNOW)
      85             :         const;
      86             : 
      87             :     void reset();
      88             : };
      89             : 
      90           0 : inline INetMIMECharsetList_Impl::Node::Node(const Charset & rTheCharset,
      91             :                                             bool bTheDisabled,
      92             :                                             Node * pTheNext):
      93             :     m_aCharset(rTheCharset),
      94             :     m_bDisabled(bTheDisabled),
      95           0 :     m_pNext(pTheNext)
      96           0 : {}
      97             : 
      98             : namespace unnamed_tools_inetmime {
      99             : 
     100           0 : struct Parameter
     101             : {
     102             :     Parameter * m_pNext;
     103             :     rtl::OString m_aAttribute;
     104             :     rtl::OString m_aCharset;
     105             :     rtl::OString m_aLanguage;
     106             :     rtl::OString m_aValue;
     107             :     sal_uInt32 m_nSection;
     108             :     bool m_bExtended;
     109             : 
     110             :     inline Parameter(Parameter * pTheNext, const rtl::OString& rTheAttribute,
     111             :                      const rtl::OString& rTheCharset,
     112             :                      const rtl::OString& rTheLanguage,
     113             :                      const rtl::OString& rTheValue, sal_uInt32 nTheSection,
     114             :                      bool bTheExtended);
     115             : };
     116             : 
     117           0 : inline Parameter::Parameter(Parameter * pTheNext,
     118             :                             const rtl::OString& rTheAttribute,
     119             :                             const rtl::OString& rTheCharset,
     120             :                             const rtl::OString& rTheLanguage,
     121             :                             const rtl::OString& rTheValue,
     122             :                             sal_uInt32 nTheSection, bool bTheExtended):
     123             :     m_pNext(pTheNext),
     124             :     m_aAttribute(rTheAttribute),
     125             :     m_aCharset(rTheCharset),
     126             :     m_aLanguage(rTheLanguage),
     127             :     m_aValue(rTheValue),
     128             :     m_nSection(nTheSection),
     129           0 :     m_bExtended(bTheExtended)
     130           0 : {}
     131             : 
     132             : struct ParameterList
     133             : {
     134             :     Parameter * m_pList;
     135             : 
     136           0 :     ParameterList(): m_pList(0) {}
     137             : 
     138             :     inline ~ParameterList();
     139             : 
     140             :     Parameter ** find(const rtl::OString& rAttribute, sal_uInt32 nSection,
     141             :                       bool & rPresent);
     142             : };
     143             : 
     144           0 : inline ParameterList::~ParameterList()
     145             : {
     146           0 :     while (m_pList)
     147             :     {
     148           0 :         Parameter * pNext = m_pList->m_pNext;
     149           0 :         delete m_pList;
     150           0 :         m_pList = pNext;
     151             :     }
     152           0 : }
     153             : 
     154             : bool parseParameters(ParameterList const & rInput,
     155             :                      INetContentTypeParameterList * pOutput);
     156             : 
     157             : }
     158             : 
     159             : //  Charset
     160             : 
     161           0 : bool Charset::contains(sal_uInt32 nChar) const
     162             : {
     163           0 :     for (const sal_uInt32 * p = m_pRanges;;)
     164             :     {
     165           0 :         if (nChar < *p++)
     166           0 :             return false;
     167           0 :         if (nChar <= *p++)
     168           0 :             return true;
     169             :     }
     170             : }
     171             : 
     172             : //  appendISO88591
     173             : 
     174             : namespace unnamed_tools_inetmime {
     175             : 
     176           6 : void appendISO88591(UniString & rText, sal_Char const * pBegin,
     177             :                     sal_Char const * pEnd)
     178             : {
     179           6 :     xub_StrLen nLength = static_cast< xub_StrLen >(pEnd - pBegin);
     180           6 :     sal_Unicode * pBuffer = new sal_Unicode[nLength];
     181          12 :     for (sal_Unicode * p = pBuffer; pBegin != pEnd;)
     182           0 :         *p++ = sal_uChar(*pBegin++);
     183           6 :     rText.Append(pBuffer, nLength);
     184           6 :     delete[] pBuffer;
     185           6 : }
     186             : 
     187             : }
     188             : 
     189             : //  INetMIMECharsetList_Impl
     190             : 
     191           0 : INetMIMECharsetList_Impl::~INetMIMECharsetList_Impl()
     192             : {
     193           0 :     while (m_pFirst)
     194             :     {
     195           0 :         Node * pRemove = m_pFirst;
     196           0 :         m_pFirst = m_pFirst->m_pNext;
     197           0 :         delete pRemove;
     198             :     }
     199           0 : }
     200             : 
     201           0 : void INetMIMECharsetList_Impl::includes(sal_uInt32 nChar)
     202             : {
     203           0 :     for (Node * p = m_pFirst; p; p = p->m_pNext)
     204           0 :         if (!(p->m_bDisabled || p->m_aCharset.contains(nChar)))
     205           0 :             p->m_bDisabled = true;
     206           0 : }
     207             : 
     208           0 : rtl_TextEncoding INetMIMECharsetList_Impl::getPreferredEncoding(rtl_TextEncoding eDefault)
     209             :     const
     210             : {
     211           0 :     for (Node * p = m_pFirst; p; p = p->m_pNext)
     212           0 :         if (!p->m_bDisabled)
     213           0 :             return p->m_aCharset.getEncoding();
     214           0 :     return eDefault;
     215             : }
     216             : 
     217           0 : void INetMIMECharsetList_Impl::reset()
     218             : {
     219           0 :     for (Node * p = m_pFirst; p; p = p->m_pNext)
     220           0 :         p->m_bDisabled = false;
     221           0 : }
     222             : 
     223             : //  ParameterList
     224             : 
     225           0 : Parameter ** ParameterList::find(const rtl::OString& rAttribute,
     226             :                                  sal_uInt32 nSection, bool & rPresent)
     227             : {
     228           0 :     Parameter ** p = &m_pList;
     229           0 :     for (; *p; p = &(*p)->m_pNext)
     230             :     {
     231           0 :         sal_Int32 nCompare = rAttribute.compareTo((*p)->m_aAttribute);
     232           0 :         if (nCompare > 0)
     233           0 :             break;
     234           0 :         else if (nCompare == 0)
     235             :         {
     236           0 :             if (nSection > (*p)->m_nSection)
     237           0 :                 break;
     238           0 :             else if (nSection == (*p)->m_nSection)
     239             :             {
     240           0 :                 rPresent = true;
     241           0 :                 return p;
     242             :             }
     243             :         }
     244             :     }
     245           0 :     rPresent = false;
     246           0 :     return p;
     247             : }
     248             : 
     249             : //  parseParameters
     250             : 
     251             : namespace unnamed_tools_inetmime {
     252             : 
     253           0 : bool parseParameters(ParameterList const & rInput,
     254             :                      INetContentTypeParameterList * pOutput)
     255             : {
     256           0 :     if (pOutput)
     257           0 :         pOutput->Clear();
     258             : 
     259           0 :     Parameter * pPrev = 0;
     260           0 :     for (Parameter * p = rInput.m_pList; p; p = p->m_pNext)
     261             :     {
     262           0 :         if (p->m_nSection > 0
     263             :             && (!pPrev
     264             :                 || pPrev->m_nSection != p->m_nSection - 1
     265           0 :                 || pPrev->m_aAttribute != p->m_aAttribute))
     266           0 :             return false;
     267           0 :         pPrev = p;
     268             :     }
     269             : 
     270           0 :     if (pOutput)
     271           0 :         for (Parameter * p = rInput.m_pList; p;)
     272             :         {
     273           0 :             bool bCharset = !p->m_aCharset.isEmpty();
     274           0 :             rtl_TextEncoding eEncoding = RTL_TEXTENCODING_DONTKNOW;
     275           0 :             if (bCharset)
     276             :                 eEncoding
     277             :                     = INetMIME::getCharsetEncoding(p->m_aCharset.getStr(),
     278           0 :                                                    p->m_aCharset.getStr()
     279             :                                                        + rInput.m_pList->
     280             :                                                              m_aCharset.
     281           0 :                                                                  getLength());
     282           0 :             UniString aValue;
     283           0 :             bool bBadEncoding = false;
     284           0 :             Parameter * pNext = p;
     285           0 :             do
     286             :             {
     287             :                 sal_Size nSize;
     288             :                 sal_Unicode * pUnicode
     289             :                     = INetMIME::convertToUnicode(pNext->m_aValue.getStr(),
     290           0 :                                                  pNext->m_aValue.getStr()
     291           0 :                                                      + pNext->m_aValue.getLength(),
     292             :                                                  bCharset && p->m_bExtended ?
     293             :                                                      eEncoding :
     294             :                                                      RTL_TEXTENCODING_UTF8,
     295           0 :                                                  nSize);
     296           0 :                 if (!pUnicode && !(bCharset && p->m_bExtended))
     297             :                     pUnicode = INetMIME::convertToUnicode(
     298             :                                    pNext->m_aValue.getStr(),
     299           0 :                                    pNext->m_aValue.getStr()
     300           0 :                                        + pNext->m_aValue.getLength(),
     301           0 :                                    RTL_TEXTENCODING_ISO_8859_1, nSize);
     302           0 :                 if (!pUnicode)
     303             :                 {
     304           0 :                     bBadEncoding = true;
     305             :                     break;
     306             :                 }
     307           0 :                 aValue += rtl::OUString(pUnicode, static_cast<sal_Int32>(nSize));
     308           0 :                 delete[] pUnicode;
     309           0 :                 pNext = pNext->m_pNext;
     310             :             }
     311             :             while (pNext && pNext->m_nSection > 0);
     312           0 :             if (bBadEncoding)
     313             :             {
     314           0 :                 aValue.Erase();
     315           0 :                 for (pNext = p;;)
     316             :                 {
     317           0 :                     if (pNext->m_bExtended)
     318             :                     {
     319           0 :                         for (sal_Int32 i = 0; i < pNext->m_aValue.getLength(); ++i)
     320             :                             aValue += sal_Unicode(
     321             :                                 sal_Unicode(
     322           0 :                                     sal_uChar(pNext->m_aValue[i]))
     323           0 :                                 | 0xF800);
     324             :                     }
     325             :                     else
     326             :                     {
     327           0 :                         for (sal_Int32 i = 0; i < pNext->m_aValue.getLength(); ++i)
     328           0 :                             aValue += sal_Unicode(sal_uChar(pNext->m_aValue[i]));
     329             :                     }
     330           0 :                     pNext = pNext->m_pNext;
     331           0 :                     if (!pNext || pNext->m_nSection == 0)
     332           0 :                         break;
     333             :                 };
     334             :             }
     335             :             pOutput->Append(new INetContentTypeParameter(p->m_aAttribute,
     336             :                                                              p->m_aCharset,
     337             :                                                              p->m_aLanguage,
     338             :                                                              aValue,
     339           0 :                                                              !bBadEncoding));
     340           0 :             p = pNext;
     341           0 :         }
     342           0 :     return true;
     343             : }
     344             : 
     345             : }
     346             : 
     347             : //  INetMIME
     348             : 
     349             : // static
     350           0 : bool INetMIME::isAtomChar(sal_uInt32 nChar)
     351             : {
     352             :     static const bool aMap[128]
     353             :         = { false, false, false, false, false, false, false, false,
     354             :             false, false, false, false, false, false, false, false,
     355             :             false, false, false, false, false, false, false, false,
     356             :             false, false, false, false, false, false, false, false,
     357             :             false,  true, false,  true,  true,  true,  true,  true, // !"#$%&'
     358             :             false, false,  true,  true, false,  true, false,  true, //()*+,-./
     359             :              true,  true,  true,  true,  true,  true,  true,  true, //01234567
     360             :              true,  true, false, false, false,  true, false,  true, //89:;<=>?
     361             :             false,  true,  true,  true,  true,  true,  true,  true, //@ABCDEFG
     362             :              true,  true,  true,  true,  true,  true,  true,  true, //HIJKLMNO
     363             :              true,  true,  true,  true,  true,  true,  true,  true, //PQRSTUVW
     364             :              true,  true,  true, false, false, false,  true,  true, //XYZ[\]^_
     365             :              true,  true,  true,  true,  true,  true,  true,  true, //`abcdefg
     366             :              true,  true,  true,  true,  true,  true,  true,  true, //hijklmno
     367             :              true,  true,  true,  true,  true,  true,  true,  true, //pqrstuvw
     368             :              true,  true,  true,  true,  true,  true,  true, false  //xyz{|}~
     369             :           };
     370           0 :     return isUSASCII(nChar) && aMap[nChar];
     371             : }
     372             : 
     373             : // static
     374           0 : bool INetMIME::isTokenChar(sal_uInt32 nChar)
     375             : {
     376             :     static const sal_Char aMap[128]
     377             :         = { false, false, false, false, false, false, false, false,
     378             :             false, false, false, false, false, false, false, false,
     379             :             false, false, false, false, false, false, false, false,
     380             :             false, false, false, false, false, false, false, false,
     381             :             false,  true, false,  true,  true,  true,  true,  true, // !"#$%&'
     382             :             false, false,  true,  true, false,  true,  true, false, //()*+,-./
     383             :              true,  true,  true,  true,  true,  true,  true,  true, //01234567
     384             :              true,  true, false, false, false, false, false, false, //89:;<=>?
     385             :             false,  true,  true,  true,  true,  true,  true,  true, //@ABCDEFG
     386             :              true,  true,  true,  true,  true,  true,  true,  true, //HIJKLMNO
     387             :              true,  true,  true,  true,  true,  true,  true,  true, //PQRSTUVW
     388             :              true,  true,  true, false, false, false,  true,  true, //XYZ[\]^_
     389             :              true,  true,  true,  true,  true,  true,  true,  true, //`abcdefg
     390             :              true,  true,  true,  true,  true,  true,  true,  true, //hijklmno
     391             :              true,  true,  true,  true,  true,  true,  true,  true, //pqrstuvw
     392             :              true,  true,  true,  true,  true,  true,  true, false  //xyz{|}~
     393             :           };
     394           0 :     return isUSASCII(nChar) && aMap[nChar];
     395             : }
     396             : 
     397             : // static
     398           0 : bool INetMIME::isEncodedWordTokenChar(sal_uInt32 nChar)
     399             : {
     400             :     static const sal_Char aMap[128]
     401             :         = { false, false, false, false, false, false, false, false,
     402             :             false, false, false, false, false, false, false, false,
     403             :             false, false, false, false, false, false, false, false,
     404             :             false, false, false, false, false, false, false, false,
     405             :             false,  true, false,  true,  true,  true,  true,  true, // !"#$%&'
     406             :             false, false,  true,  true, false,  true, false, false, //()*+,-./
     407             :              true,  true,  true,  true,  true,  true,  true,  true, //01234567
     408             :              true,  true, false, false, false, false, false, false, //89:;<=>?
     409             :             false,  true,  true,  true,  true,  true,  true,  true, //@ABCDEFG
     410             :              true,  true,  true,  true,  true,  true,  true,  true, //HIJKLMNO
     411             :              true,  true,  true,  true,  true,  true,  true,  true, //PQRSTUVW
     412             :              true,  true,  true, false, false, false,  true,  true, //XYZ[\]^_
     413             :              true,  true,  true,  true,  true,  true,  true,  true, //`abcdefg
     414             :              true,  true,  true,  true,  true,  true,  true,  true, //hijklmno
     415             :              true,  true,  true,  true,  true,  true,  true,  true, //pqrstuvw
     416             :              true,  true,  true,  true,  true,  true,  true, false  //xyz{|}~
     417             :           };
     418           0 :     return isUSASCII(nChar) && aMap[nChar];
     419             : }
     420             : 
     421             : // static
     422           0 : bool INetMIME::isIMAPAtomChar(sal_uInt32 nChar)
     423             : {
     424             :     static const sal_Char aMap[128]
     425             :         = { false, false, false, false, false, false, false, false,
     426             :             false, false, false, false, false, false, false, false,
     427             :             false, false, false, false, false, false, false, false,
     428             :             false, false, false, false, false, false, false, false,
     429             :             false,  true, false,  true,  true, false,  true,  true, // !"#$%&'
     430             :             false, false, false,  true,  true,  true,  true,  true, //()*+,-./
     431             :              true,  true,  true,  true,  true,  true,  true,  true, //01234567
     432             :              true,  true,  true,  true,  true,  true,  true,  true, //89:;<=>?
     433             :              true,  true,  true,  true,  true,  true,  true,  true, //@ABCDEFG
     434             :              true,  true,  true,  true,  true,  true,  true,  true, //HIJKLMNO
     435             :              true,  true,  true,  true,  true,  true,  true,  true, //PQRSTUVW
     436             :              true,  true,  true,  true, false,  true,  true,  true, //XYZ[\]^_
     437             :              true,  true,  true,  true,  true,  true,  true,  true, //`abcdefg
     438             :              true,  true,  true,  true,  true,  true,  true,  true, //hijklmno
     439             :              true,  true,  true,  true,  true,  true,  true,  true, //pqrstuvw
     440             :              true,  true,  true, false,  true,  true,  true, false  //xyz{|}~
     441             :           };
     442           0 :     return isUSASCII(nChar) && aMap[nChar];
     443             : }
     444             : 
     445             : // static
     446       22082 : sal_uInt32 INetMIME::getHexDigit(int nWeight)
     447             : {
     448             :     DBG_ASSERT(nWeight >= 0 && nWeight < 16,
     449             :                "INetMIME::getHexDigit(): Bad weight");
     450             : 
     451             :     static const sal_Char aDigits[16]
     452             :         = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
     453             :             'D', 'E', 'F' };
     454       22082 :     return aDigits[nWeight];
     455             : }
     456             : 
     457             : // static
     458          36 : bool INetMIME::equalIgnoreCase(const sal_Char * pBegin1,
     459             :                                const sal_Char * pEnd1,
     460             :                                const sal_Char * pString2)
     461             : {
     462             :     DBG_ASSERT(pBegin1 && pBegin1 <= pEnd1 && pString2,
     463             :                "INetMIME::equalIgnoreCase(): Bad sequences");
     464             : 
     465         135 :     while (*pString2 != 0)
     466         192 :         if (pBegin1 == pEnd1
     467          96 :             || toUpperCase(*pBegin1++) != toUpperCase(*pString2++))
     468          33 :             return false;
     469           3 :     return pBegin1 == pEnd1;
     470             : }
     471             : 
     472             : // static
     473       28338 : bool INetMIME::equalIgnoreCase(const sal_Unicode * pBegin1,
     474             :                                const sal_Unicode * pEnd1,
     475             :                                const sal_Char * pString2)
     476             : {
     477             :     DBG_ASSERT(pBegin1 && pBegin1 <= pEnd1 && pString2,
     478             :                "INetMIME::equalIgnoreCase(): Bad sequences");
     479             : 
     480       56676 :     while (*pString2 != 0)
     481       28343 :         if (pBegin1 == pEnd1
     482           5 :             || toUpperCase(*pBegin1++) != toUpperCase(*pString2++))
     483       28338 :             return false;
     484           0 :     return pBegin1 == pEnd1;
     485             : }
     486             : 
     487             : // static
     488           0 : const sal_Unicode * INetMIME::skipLinearWhiteSpace(const sal_Unicode * pBegin,
     489             :                                                    const sal_Unicode * pEnd)
     490             : {
     491             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
     492             :                "INetMIME::skipLinearWhiteSpace(): Bad sequence");
     493             : 
     494           0 :     while (pBegin != pEnd)
     495           0 :         switch (*pBegin)
     496             :         {
     497             :             case '\t':
     498             :             case ' ':
     499           0 :                 ++pBegin;
     500           0 :                 break;
     501             : 
     502             :             case 0x0D: // CR
     503           0 :                 if (startsWithLineFolding(pBegin, pEnd))
     504           0 :                     pBegin += 3;
     505             :                 else
     506           0 :                     return pBegin;
     507           0 :                 break;
     508             : 
     509             :             default:
     510           0 :                 return pBegin;
     511             :         }
     512           0 :     return pBegin;
     513             : }
     514             : 
     515             : // static
     516           0 : const sal_Unicode * INetMIME::skipComment(const sal_Unicode * pBegin,
     517             :                                           const sal_Unicode * pEnd)
     518             : {
     519             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
     520             :                "INetMIME::skipComment(): Bad sequence");
     521             : 
     522           0 :     if (pBegin != pEnd && *pBegin == '(')
     523             :     {
     524           0 :         sal_uInt32 nLevel = 0;
     525           0 :         for (const sal_Unicode * p = pBegin; p != pEnd;)
     526           0 :             switch (*p++)
     527             :             {
     528             :                 case '(':
     529           0 :                     ++nLevel;
     530           0 :                     break;
     531             : 
     532             :                 case ')':
     533           0 :                     if (--nLevel == 0)
     534           0 :                         return p;
     535           0 :                     break;
     536             : 
     537             :                 case '\\':
     538           0 :                     if (p != pEnd)
     539           0 :                         ++p;
     540           0 :                     break;
     541             :             }
     542             :     }
     543           0 :     return pBegin;
     544             : }
     545             : 
     546             : // static
     547           0 : const sal_Unicode * INetMIME::skipLinearWhiteSpaceComment(const sal_Unicode *
     548             :                                                               pBegin,
     549             :                                                           const sal_Unicode *
     550             :                                                               pEnd)
     551             : {
     552             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
     553             :                "INetMIME::skipLinearWhiteSpaceComment(): Bad sequence");
     554             : 
     555           0 :     while (pBegin != pEnd)
     556           0 :         switch (*pBegin)
     557             :         {
     558             :             case '\t':
     559             :             case ' ':
     560           0 :                 ++pBegin;
     561           0 :                 break;
     562             : 
     563             :             case 0x0D: // CR
     564           0 :                 if (startsWithLineFolding(pBegin, pEnd))
     565           0 :                     pBegin += 3;
     566             :                 else
     567           0 :                     return pBegin;
     568           0 :                 break;
     569             : 
     570             :             case '(':
     571             :             {
     572           0 :                 const sal_Unicode * p = skipComment(pBegin, pEnd);
     573           0 :                 if (p == pBegin)
     574           0 :                     return pBegin;
     575           0 :                 pBegin = p;
     576           0 :                 break;
     577             :             }
     578             : 
     579             :             default:
     580           0 :                 return pBegin;
     581             :         }
     582           0 :     return pBegin;
     583             : }
     584             : 
     585             : // static
     586           0 : const sal_Char * INetMIME::skipQuotedString(const sal_Char * pBegin,
     587             :                                             const sal_Char * pEnd)
     588             : {
     589             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
     590             :                "INetMIME::skipQuotedString(): Bad sequence");
     591             : 
     592           0 :     if (pBegin != pEnd && *pBegin == '"')
     593           0 :         for (const sal_Char * p = pBegin + 1; p != pEnd;)
     594           0 :             switch (*p++)
     595             :             {
     596             :                 case 0x0D: // CR
     597           0 :                     if (pEnd - p < 2 || *p++ != 0x0A // LF
     598           0 :                         || !isWhiteSpace(*p++))
     599           0 :                         return pBegin;
     600           0 :                     break;
     601             : 
     602             :                 case '"':
     603           0 :                     return p;
     604             : 
     605             :                 case '\\':
     606           0 :                     if (p != pEnd)
     607           0 :                         ++p;
     608           0 :                     break;
     609             :             }
     610           0 :     return pBegin;
     611             : }
     612             : 
     613             : // static
     614           0 : const sal_Unicode * INetMIME::skipQuotedString(const sal_Unicode * pBegin,
     615             :                                                const sal_Unicode * pEnd)
     616             : {
     617             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
     618             :                "INetMIME::skipQuotedString(): Bad sequence");
     619             : 
     620           0 :     if (pBegin != pEnd && *pBegin == '"')
     621           0 :         for (const sal_Unicode * p = pBegin + 1; p != pEnd;)
     622           0 :             switch (*p++)
     623             :             {
     624             :                 case 0x0D: // CR
     625           0 :                     if (pEnd - p < 2 || *p++ != 0x0A // LF
     626           0 :                         || !isWhiteSpace(*p++))
     627           0 :                         return pBegin;
     628           0 :                     break;
     629             : 
     630             :                 case '"':
     631           0 :                     return p;
     632             : 
     633             :                 case '\\':
     634           0 :                     if (p != pEnd)
     635           0 :                         ++p;
     636           0 :                     break;
     637             :             }
     638           0 :     return pBegin;
     639             : }
     640             : 
     641             : // static
     642           0 : bool INetMIME::scanUnsigned(const sal_Unicode *& rBegin,
     643             :                             const sal_Unicode * pEnd, bool bLeadingZeroes,
     644             :                             sal_uInt32 & rValue)
     645             : {
     646           0 :     sal_uInt64 nTheValue = 0;
     647           0 :     const sal_Unicode * p = rBegin;
     648           0 :     for ( ; p != pEnd; ++p)
     649             :     {
     650           0 :         int nWeight = getWeight(*p);
     651           0 :         if (nWeight < 0)
     652           0 :             break;
     653           0 :         nTheValue = 10 * nTheValue + nWeight;
     654           0 :         if (nTheValue > std::numeric_limits< sal_uInt32 >::max())
     655           0 :             return false;
     656             :     }
     657           0 :     if (nTheValue == 0 && (p == rBegin || (!bLeadingZeroes && p - rBegin != 1)))
     658           0 :         return false;
     659           0 :     rBegin = p;
     660           0 :     rValue = sal_uInt32(nTheValue);
     661           0 :     return true;
     662             : }
     663             : 
     664             : // static
     665           0 : const sal_Unicode * INetMIME::scanQuotedBlock(const sal_Unicode * pBegin,
     666             :                                               const sal_Unicode * pEnd,
     667             :                                               sal_uInt32 nOpening,
     668             :                                               sal_uInt32 nClosing,
     669             :                                               sal_Size & rLength,
     670             :                                               bool & rModify)
     671             : {
     672             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
     673             :                "INetMIME::scanQuotedBlock(): Bad sequence");
     674             : 
     675           0 :     if (pBegin != pEnd && *pBegin == nOpening)
     676             :     {
     677           0 :         ++rLength;
     678           0 :         ++pBegin;
     679           0 :         while (pBegin != pEnd)
     680           0 :             if (*pBegin == nClosing)
     681             :             {
     682           0 :                 ++rLength;
     683           0 :                 return ++pBegin;
     684             :             }
     685             :             else
     686             :             {
     687           0 :                 sal_uInt32 c = *pBegin++;
     688           0 :                 switch (c)
     689             :                 {
     690             :                     case 0x0D: // CR
     691           0 :                         if (pBegin != pEnd && *pBegin == 0x0A) // LF
     692           0 :                             if (pEnd - pBegin >= 2 && isWhiteSpace(pBegin[1]))
     693             :                             {
     694           0 :                                 ++rLength;
     695           0 :                                 rModify = true;
     696           0 :                                 pBegin += 2;
     697             :                             }
     698             :                             else
     699             :                             {
     700           0 :                                 rLength += 3;
     701           0 :                                 rModify = true;
     702           0 :                                 ++pBegin;
     703             :                             }
     704             :                         else
     705           0 :                             ++rLength;
     706           0 :                         break;
     707             : 
     708             :                     case '\\':
     709           0 :                         ++rLength;
     710           0 :                         if (pBegin != pEnd)
     711             :                         {
     712           0 :                             if (startsWithLineBreak(pBegin, pEnd)
     713             :                                 && (pEnd - pBegin < 3
     714           0 :                                     || !isWhiteSpace(pBegin[2])))
     715             :                             {
     716           0 :                                 rLength += 3;
     717           0 :                                 rModify = true;
     718           0 :                                 pBegin += 2;
     719             :                             }
     720             :                             else
     721           0 :                                 ++pBegin;
     722             :                         }
     723           0 :                         break;
     724             : 
     725             :                     default:
     726           0 :                         ++rLength;
     727           0 :                         if (!isUSASCII(c))
     728           0 :                             rModify = true;
     729           0 :                         break;
     730             :                 }
     731             :             }
     732             :     }
     733           0 :     return pBegin;
     734             : }
     735             : 
     736             : // static
     737           0 : sal_Unicode const * INetMIME::scanParameters(sal_Unicode const * pBegin,
     738             :                                              sal_Unicode const * pEnd,
     739             :                                              INetContentTypeParameterList *
     740             :                                                  pParameters)
     741             : {
     742           0 :     ParameterList aList;
     743           0 :     sal_Unicode const * pParameterBegin = pBegin;
     744           0 :     for (sal_Unicode const * p = pParameterBegin;; pParameterBegin = p)
     745             :     {
     746           0 :         pParameterBegin = skipLinearWhiteSpaceComment(p, pEnd);
     747           0 :         if (pParameterBegin == pEnd || *pParameterBegin != ';')
     748             :             break;
     749           0 :         p = pParameterBegin + 1;
     750             : 
     751             :         sal_Unicode const * pAttributeBegin
     752           0 :             = skipLinearWhiteSpaceComment(p, pEnd);
     753           0 :         p = pAttributeBegin;
     754           0 :         bool bDowncaseAttribute = false;
     755           0 :         while (p != pEnd && isTokenChar(*p) && *p != '*')
     756             :         {
     757           0 :             bDowncaseAttribute = bDowncaseAttribute || isUpperCase(*p);
     758           0 :             ++p;
     759             :         }
     760           0 :         if (p == pAttributeBegin)
     761             :             break;
     762             :         rtl::OString aAttribute = rtl::OString(
     763             :             pAttributeBegin, p - pAttributeBegin,
     764           0 :             RTL_TEXTENCODING_ASCII_US);
     765           0 :         if (bDowncaseAttribute)
     766           0 :             aAttribute = aAttribute.toAsciiLowerCase();
     767             : 
     768           0 :         sal_uInt32 nSection = 0;
     769           0 :         if (p != pEnd && *p == '*')
     770             :         {
     771           0 :             ++p;
     772           0 :             if (p != pEnd && isDigit(*p)
     773           0 :                 && !scanUnsigned(p, pEnd, false, nSection))
     774             :                 break;
     775             :         }
     776             : 
     777             :         bool bPresent;
     778           0 :         Parameter ** pPos = aList.find(aAttribute, nSection, bPresent);
     779           0 :         if (bPresent)
     780             :             break;
     781             : 
     782           0 :         bool bExtended = false;
     783           0 :         if (p != pEnd && *p == '*')
     784             :         {
     785           0 :             ++p;
     786           0 :             bExtended = true;
     787             :         }
     788             : 
     789           0 :         p = skipLinearWhiteSpaceComment(p, pEnd);
     790             : 
     791           0 :         if (p == pEnd || *p != '=')
     792             :             break;
     793             : 
     794           0 :         p = skipLinearWhiteSpaceComment(p + 1, pEnd);
     795             : 
     796           0 :         rtl::OString aCharset;
     797           0 :         rtl::OString aLanguage;
     798           0 :         rtl::OString aValue;
     799           0 :         if (bExtended)
     800             :         {
     801           0 :             if (nSection == 0)
     802             :             {
     803           0 :                 sal_Unicode const * pCharsetBegin = p;
     804           0 :                 bool bDowncaseCharset = false;
     805           0 :                 while (p != pEnd && isTokenChar(*p) && *p != '\'')
     806             :                 {
     807           0 :                     bDowncaseCharset = bDowncaseCharset || isUpperCase(*p);
     808           0 :                     ++p;
     809             :                 }
     810           0 :                 if (p == pCharsetBegin)
     811             :                     break;
     812           0 :                 if (pParameters)
     813             :                 {
     814             :                     aCharset = rtl::OString(
     815             :                         pCharsetBegin,
     816             :                         p - pCharsetBegin,
     817           0 :                         RTL_TEXTENCODING_ASCII_US);
     818           0 :                     if (bDowncaseCharset)
     819           0 :                         aCharset = aCharset.toAsciiLowerCase();
     820             :                 }
     821             : 
     822           0 :                 if (p == pEnd || *p != '\'')
     823             :                     break;
     824           0 :                 ++p;
     825             : 
     826           0 :                 sal_Unicode const * pLanguageBegin = p;
     827           0 :                 bool bDowncaseLanguage = false;
     828           0 :                 int nLetters = 0;
     829           0 :                 for (; p != pEnd; ++p)
     830           0 :                     if (isAlpha(*p))
     831             :                     {
     832           0 :                         if (++nLetters > 8)
     833           0 :                             break;
     834             :                         bDowncaseLanguage = bDowncaseLanguage
     835           0 :                                             || isUpperCase(*p);
     836             :                     }
     837           0 :                     else if (*p == '-')
     838             :                     {
     839           0 :                         if (nLetters == 0)
     840           0 :                             break;
     841           0 :                         nLetters = 0;
     842             :                     }
     843             :                     else
     844           0 :                         break;
     845           0 :                 if (nLetters == 0 || nLetters > 8)
     846             :                     break;
     847           0 :                 if (pParameters)
     848             :                 {
     849             :                     aLanguage = rtl::OString(
     850             :                         pLanguageBegin,
     851             :                         p - pLanguageBegin,
     852           0 :                         RTL_TEXTENCODING_ASCII_US);
     853           0 :                     if (bDowncaseLanguage)
     854           0 :                         aLanguage = aLanguage.toAsciiLowerCase();
     855             :                 }
     856             : 
     857           0 :                 if (p == pEnd || *p != '\'')
     858             :                     break;
     859           0 :                 ++p;
     860             :             }
     861           0 :             if (pParameters)
     862             :             {
     863             :                 INetMIMEStringOutputSink
     864           0 :                     aSink(0, INetMIMEOutputSink::NO_LINE_LENGTH_LIMIT);
     865           0 :                 while (p != pEnd)
     866             :                 {
     867           0 :                     sal_uInt32 nChar = INetMIME::getUTF32Character(p, pEnd);
     868           0 :                     if (isUSASCII(nChar) && !isTokenChar(nChar))
     869           0 :                         break;
     870           0 :                     if (nChar == '%' && p + 1 < pEnd)
     871             :                     {
     872           0 :                         int nWeight1 = getHexWeight(p[0]);
     873           0 :                         int nWeight2 = getHexWeight(p[1]);
     874           0 :                         if (nWeight1 >= 0 && nWeight2 >= 0)
     875             :                         {
     876           0 :                             aSink << sal_Char(nWeight1 << 4 | nWeight2);
     877           0 :                             p += 2;
     878           0 :                             continue;
     879             :                         }
     880             :                     }
     881           0 :                     INetMIME::writeUTF8(aSink, nChar);
     882             :                 }
     883           0 :                 aValue = aSink.takeBuffer();
     884             :             }
     885             :             else
     886           0 :                 while (p != pEnd && (isTokenChar(*p) || !isUSASCII(*p)))
     887           0 :                     ++p;
     888             :         }
     889           0 :         else if (p != pEnd && *p == '"')
     890           0 :             if (pParameters)
     891             :             {
     892             :                 INetMIMEStringOutputSink
     893           0 :                     aSink(0, INetMIMEOutputSink::NO_LINE_LENGTH_LIMIT);
     894           0 :                 bool bInvalid = false;
     895           0 :                 for (++p;;)
     896             :                 {
     897           0 :                     if (p == pEnd)
     898             :                     {
     899           0 :                         bInvalid = true;
     900           0 :                         break;
     901             :                     }
     902           0 :                     sal_uInt32 nChar = INetMIME::getUTF32Character(p, pEnd);
     903           0 :                     if (nChar == '"')
     904           0 :                         break;
     905           0 :                     else if (nChar == 0x0D) // CR
     906             :                     {
     907           0 :                         if (pEnd - p < 2 || *p++ != 0x0A // LF
     908           0 :                             || !isWhiteSpace(*p))
     909             :                         {
     910           0 :                             bInvalid = true;
     911           0 :                             break;
     912             :                         }
     913           0 :                         nChar = sal_uChar(*p++);
     914             :                     }
     915           0 :                     else if (nChar == '\\')
     916             :                     {
     917           0 :                         if (p == pEnd)
     918             :                         {
     919           0 :                             bInvalid = true;
     920           0 :                             break;
     921             :                         }
     922           0 :                         nChar = INetMIME::getUTF32Character(p, pEnd);
     923             :                     }
     924           0 :                     INetMIME::writeUTF8(aSink, nChar);
     925             :                 }
     926           0 :                 if (bInvalid)
     927             :                     break;
     928           0 :                 aValue = aSink.takeBuffer();
     929             :             }
     930             :             else
     931             :             {
     932           0 :                 sal_Unicode const * pStringEnd = skipQuotedString(p, pEnd);
     933           0 :                 if (p == pStringEnd)
     934             :                     break;
     935           0 :                 p = pStringEnd;
     936           0 :             }
     937             :         else
     938             :         {
     939           0 :             sal_Unicode const * pTokenBegin = p;
     940           0 :             while (p != pEnd && (isTokenChar(*p) || !isUSASCII(*p)))
     941           0 :                 ++p;
     942           0 :             if (p == pTokenBegin)
     943             :                 break;
     944           0 :             if (pParameters)
     945             :                 aValue = rtl::OString(
     946             :                     pTokenBegin, p - pTokenBegin,
     947           0 :                     RTL_TEXTENCODING_UTF8);
     948             :         }
     949             : 
     950             :         *pPos = new Parameter(*pPos, aAttribute, aCharset, aLanguage, aValue,
     951           0 :                               nSection, bExtended);
     952           0 :     }
     953           0 :     return parseParameters(aList, pParameters) ? pParameterBegin : pBegin;
     954             : }
     955             : 
     956             : // static
     957           0 : const sal_Char * INetMIME::getCharsetName(rtl_TextEncoding eEncoding)
     958             : {
     959           0 :     if (rtl_isOctetTextEncoding(eEncoding))
     960             :     {
     961           0 :         char const * p = rtl_getMimeCharsetFromTextEncoding(eEncoding);
     962             :         DBG_ASSERT(p, "INetMIME::getCharsetName(): Unsupported encoding");
     963           0 :         return p;
     964             :     }
     965             :     else
     966           0 :         switch (eEncoding)
     967             :         {
     968             :             case RTL_TEXTENCODING_UCS4:
     969           0 :                 return "ISO-10646-UCS-4";
     970             : 
     971             :             case RTL_TEXTENCODING_UCS2:
     972           0 :                 return "ISO-10646-UCS-2";
     973             : 
     974             :             default:
     975             :                 OSL_FAIL("INetMIME::getCharsetName(): Unsupported encoding");
     976           0 :                 return 0;
     977             :         }
     978             : }
     979             : 
     980             : namespace unnamed_tools_inetmime {
     981             : 
     982             : struct EncodingEntry
     983             : {
     984             :     sal_Char const * m_aName;
     985             :     rtl_TextEncoding m_eEncoding;
     986             : };
     987             : 
     988             : // The source for the following table is <ftp://ftp.iana.org/in-notes/iana/
     989             : // assignments/character-sets> as of Jan, 21 2000 12:46:00, unless  otherwise
     990             : // noted:
     991             : EncodingEntry const aEncodingMap[]
     992             :     = { { "US-ASCII", RTL_TEXTENCODING_ASCII_US },
     993             :         { "ANSI_X3.4-1968", RTL_TEXTENCODING_ASCII_US },
     994             :         { "ISO-IR-6", RTL_TEXTENCODING_ASCII_US },
     995             :         { "ANSI_X3.4-1986", RTL_TEXTENCODING_ASCII_US },
     996             :         { "ISO_646.IRV:1991", RTL_TEXTENCODING_ASCII_US },
     997             :         { "ASCII", RTL_TEXTENCODING_ASCII_US },
     998             :         { "ISO646-US", RTL_TEXTENCODING_ASCII_US },
     999             :         { "US", RTL_TEXTENCODING_ASCII_US },
    1000             :         { "IBM367", RTL_TEXTENCODING_ASCII_US },
    1001             :         { "CP367", RTL_TEXTENCODING_ASCII_US },
    1002             :         { "CSASCII", RTL_TEXTENCODING_ASCII_US },
    1003             :         { "ISO-8859-1", RTL_TEXTENCODING_ISO_8859_1 },
    1004             :         { "ISO_8859-1:1987", RTL_TEXTENCODING_ISO_8859_1 },
    1005             :         { "ISO-IR-100", RTL_TEXTENCODING_ISO_8859_1 },
    1006             :         { "ISO_8859-1", RTL_TEXTENCODING_ISO_8859_1 },
    1007             :         { "LATIN1", RTL_TEXTENCODING_ISO_8859_1 },
    1008             :         { "L1", RTL_TEXTENCODING_ISO_8859_1 },
    1009             :         { "IBM819", RTL_TEXTENCODING_ISO_8859_1 },
    1010             :         { "CP819", RTL_TEXTENCODING_ISO_8859_1 },
    1011             :         { "CSISOLATIN1", RTL_TEXTENCODING_ISO_8859_1 },
    1012             :         { "ISO-8859-2", RTL_TEXTENCODING_ISO_8859_2 },
    1013             :         { "ISO_8859-2:1987", RTL_TEXTENCODING_ISO_8859_2 },
    1014             :         { "ISO-IR-101", RTL_TEXTENCODING_ISO_8859_2 },
    1015             :         { "ISO_8859-2", RTL_TEXTENCODING_ISO_8859_2 },
    1016             :         { "LATIN2", RTL_TEXTENCODING_ISO_8859_2 },
    1017             :         { "L2", RTL_TEXTENCODING_ISO_8859_2 },
    1018             :         { "CSISOLATIN2", RTL_TEXTENCODING_ISO_8859_2 },
    1019             :         { "ISO-8859-3", RTL_TEXTENCODING_ISO_8859_3 },
    1020             :         { "ISO_8859-3:1988", RTL_TEXTENCODING_ISO_8859_3 },
    1021             :         { "ISO-IR-109", RTL_TEXTENCODING_ISO_8859_3 },
    1022             :         { "ISO_8859-3", RTL_TEXTENCODING_ISO_8859_3 },
    1023             :         { "LATIN3", RTL_TEXTENCODING_ISO_8859_3 },
    1024             :         { "L3", RTL_TEXTENCODING_ISO_8859_3 },
    1025             :         { "CSISOLATIN3", RTL_TEXTENCODING_ISO_8859_3 },
    1026             :         { "ISO-8859-4", RTL_TEXTENCODING_ISO_8859_4 },
    1027             :         { "ISO_8859-4:1988", RTL_TEXTENCODING_ISO_8859_4 },
    1028             :         { "ISO-IR-110", RTL_TEXTENCODING_ISO_8859_4 },
    1029             :         { "ISO_8859-4", RTL_TEXTENCODING_ISO_8859_4 },
    1030             :         { "LATIN4", RTL_TEXTENCODING_ISO_8859_4 },
    1031             :         { "L4", RTL_TEXTENCODING_ISO_8859_4 },
    1032             :         { "CSISOLATIN4", RTL_TEXTENCODING_ISO_8859_4 },
    1033             :         { "ISO-8859-5", RTL_TEXTENCODING_ISO_8859_5 },
    1034             :         { "ISO_8859-5:1988", RTL_TEXTENCODING_ISO_8859_5 },
    1035             :         { "ISO-IR-144", RTL_TEXTENCODING_ISO_8859_5 },
    1036             :         { "ISO_8859-5", RTL_TEXTENCODING_ISO_8859_5 },
    1037             :         { "CYRILLIC", RTL_TEXTENCODING_ISO_8859_5 },
    1038             :         { "CSISOLATINCYRILLIC", RTL_TEXTENCODING_ISO_8859_5 },
    1039             :         { "ISO-8859-6", RTL_TEXTENCODING_ISO_8859_6 },
    1040             :         { "ISO_8859-6:1987", RTL_TEXTENCODING_ISO_8859_6 },
    1041             :         { "ISO-IR-127", RTL_TEXTENCODING_ISO_8859_6 },
    1042             :         { "ISO_8859-6", RTL_TEXTENCODING_ISO_8859_6 },
    1043             :         { "ECMA-114", RTL_TEXTENCODING_ISO_8859_6 },
    1044             :         { "ASMO-708", RTL_TEXTENCODING_ISO_8859_6 },
    1045             :         { "ARABIC", RTL_TEXTENCODING_ISO_8859_6 },
    1046             :         { "CSISOLATINARABIC", RTL_TEXTENCODING_ISO_8859_6 },
    1047             :         { "ISO-8859-7", RTL_TEXTENCODING_ISO_8859_7 },
    1048             :         { "ISO_8859-7:1987", RTL_TEXTENCODING_ISO_8859_7 },
    1049             :         { "ISO-IR-126", RTL_TEXTENCODING_ISO_8859_7 },
    1050             :         { "ISO_8859-7", RTL_TEXTENCODING_ISO_8859_7 },
    1051             :         { "ELOT_928", RTL_TEXTENCODING_ISO_8859_7 },
    1052             :         { "ECMA-118", RTL_TEXTENCODING_ISO_8859_7 },
    1053             :         { "GREEK", RTL_TEXTENCODING_ISO_8859_7 },
    1054             :         { "GREEK8", RTL_TEXTENCODING_ISO_8859_7 },
    1055             :         { "CSISOLATINGREEK", RTL_TEXTENCODING_ISO_8859_7 },
    1056             :         { "ISO-8859-8", RTL_TEXTENCODING_ISO_8859_8 },
    1057             :         { "ISO_8859-8:1988", RTL_TEXTENCODING_ISO_8859_8 },
    1058             :         { "ISO-IR-138", RTL_TEXTENCODING_ISO_8859_8 },
    1059             :         { "ISO_8859-8", RTL_TEXTENCODING_ISO_8859_8 },
    1060             :         { "HEBREW", RTL_TEXTENCODING_ISO_8859_8 },
    1061             :         { "CSISOLATINHEBREW", RTL_TEXTENCODING_ISO_8859_8 },
    1062             :         { "ISO-8859-9", RTL_TEXTENCODING_ISO_8859_9 },
    1063             :         { "ISO_8859-9:1989", RTL_TEXTENCODING_ISO_8859_9 },
    1064             :         { "ISO-IR-148", RTL_TEXTENCODING_ISO_8859_9 },
    1065             :         { "ISO_8859-9", RTL_TEXTENCODING_ISO_8859_9 },
    1066             :         { "LATIN5", RTL_TEXTENCODING_ISO_8859_9 },
    1067             :         { "L5", RTL_TEXTENCODING_ISO_8859_9 },
    1068             :         { "CSISOLATIN5", RTL_TEXTENCODING_ISO_8859_9 },
    1069             :         { "ISO-8859-14", RTL_TEXTENCODING_ISO_8859_14 }, // RFC 2047
    1070             :         { "ISO_8859-15", RTL_TEXTENCODING_ISO_8859_15 },
    1071             :         { "ISO-8859-15", RTL_TEXTENCODING_ISO_8859_15 }, // RFC 2047
    1072             :         { "MACINTOSH", RTL_TEXTENCODING_APPLE_ROMAN },
    1073             :         { "MAC", RTL_TEXTENCODING_APPLE_ROMAN },
    1074             :         { "CSMACINTOSH", RTL_TEXTENCODING_APPLE_ROMAN },
    1075             :         { "IBM437", RTL_TEXTENCODING_IBM_437 },
    1076             :         { "CP437", RTL_TEXTENCODING_IBM_437 },
    1077             :         { "437", RTL_TEXTENCODING_IBM_437 },
    1078             :         { "CSPC8CODEPAGE437", RTL_TEXTENCODING_IBM_437 },
    1079             :         { "IBM850", RTL_TEXTENCODING_IBM_850 },
    1080             :         { "CP850", RTL_TEXTENCODING_IBM_850 },
    1081             :         { "850", RTL_TEXTENCODING_IBM_850 },
    1082             :         { "CSPC850MULTILINGUAL", RTL_TEXTENCODING_IBM_850 },
    1083             :         { "IBM860", RTL_TEXTENCODING_IBM_860 },
    1084             :         { "CP860", RTL_TEXTENCODING_IBM_860 },
    1085             :         { "860", RTL_TEXTENCODING_IBM_860 },
    1086             :         { "CSIBM860", RTL_TEXTENCODING_IBM_860 },
    1087             :         { "IBM861", RTL_TEXTENCODING_IBM_861 },
    1088             :         { "CP861", RTL_TEXTENCODING_IBM_861 },
    1089             :         { "861", RTL_TEXTENCODING_IBM_861 },
    1090             :         { "CP-IS", RTL_TEXTENCODING_IBM_861 },
    1091             :         { "CSIBM861", RTL_TEXTENCODING_IBM_861 },
    1092             :         { "IBM863", RTL_TEXTENCODING_IBM_863 },
    1093             :         { "CP863", RTL_TEXTENCODING_IBM_863 },
    1094             :         { "863", RTL_TEXTENCODING_IBM_863 },
    1095             :         { "CSIBM863", RTL_TEXTENCODING_IBM_863 },
    1096             :         { "IBM865", RTL_TEXTENCODING_IBM_865 },
    1097             :         { "CP865", RTL_TEXTENCODING_IBM_865 },
    1098             :         { "865", RTL_TEXTENCODING_IBM_865 },
    1099             :         { "CSIBM865", RTL_TEXTENCODING_IBM_865 },
    1100             :         { "IBM775", RTL_TEXTENCODING_IBM_775 },
    1101             :         { "CP775", RTL_TEXTENCODING_IBM_775 },
    1102             :         { "CSPC775BALTIC", RTL_TEXTENCODING_IBM_775 },
    1103             :         { "IBM852", RTL_TEXTENCODING_IBM_852 },
    1104             :         { "CP852", RTL_TEXTENCODING_IBM_852 },
    1105             :         { "852", RTL_TEXTENCODING_IBM_852 },
    1106             :         { "CSPCP852", RTL_TEXTENCODING_IBM_852 },
    1107             :         { "IBM855", RTL_TEXTENCODING_IBM_855 },
    1108             :         { "CP855", RTL_TEXTENCODING_IBM_855 },
    1109             :         { "855", RTL_TEXTENCODING_IBM_855 },
    1110             :         { "CSIBM855", RTL_TEXTENCODING_IBM_855 },
    1111             :         { "IBM857", RTL_TEXTENCODING_IBM_857 },
    1112             :         { "CP857", RTL_TEXTENCODING_IBM_857 },
    1113             :         { "857", RTL_TEXTENCODING_IBM_857 },
    1114             :         { "CSIBM857", RTL_TEXTENCODING_IBM_857 },
    1115             :         { "IBM862", RTL_TEXTENCODING_IBM_862 },
    1116             :         { "CP862", RTL_TEXTENCODING_IBM_862 },
    1117             :         { "862", RTL_TEXTENCODING_IBM_862 },
    1118             :         { "CSPC862LATINHEBREW", RTL_TEXTENCODING_IBM_862 },
    1119             :         { "IBM864", RTL_TEXTENCODING_IBM_864 },
    1120             :         { "CP864", RTL_TEXTENCODING_IBM_864 },
    1121             :         { "CSIBM864", RTL_TEXTENCODING_IBM_864 },
    1122             :         { "IBM866", RTL_TEXTENCODING_IBM_866 },
    1123             :         { "CP866", RTL_TEXTENCODING_IBM_866 },
    1124             :         { "866", RTL_TEXTENCODING_IBM_866 },
    1125             :         { "CSIBM866", RTL_TEXTENCODING_IBM_866 },
    1126             :         { "IBM869", RTL_TEXTENCODING_IBM_869 },
    1127             :         { "CP869", RTL_TEXTENCODING_IBM_869 },
    1128             :         { "869", RTL_TEXTENCODING_IBM_869 },
    1129             :         { "CP-GR", RTL_TEXTENCODING_IBM_869 },
    1130             :         { "CSIBM869", RTL_TEXTENCODING_IBM_869 },
    1131             :         { "WINDOWS-1250", RTL_TEXTENCODING_MS_1250 },
    1132             :         { "WINDOWS-1251", RTL_TEXTENCODING_MS_1251 },
    1133             :         { "WINDOWS-1253", RTL_TEXTENCODING_MS_1253 },
    1134             :         { "WINDOWS-1254", RTL_TEXTENCODING_MS_1254 },
    1135             :         { "WINDOWS-1255", RTL_TEXTENCODING_MS_1255 },
    1136             :         { "WINDOWS-1256", RTL_TEXTENCODING_MS_1256 },
    1137             :         { "WINDOWS-1257", RTL_TEXTENCODING_MS_1257 },
    1138             :         { "WINDOWS-1258", RTL_TEXTENCODING_MS_1258 },
    1139             :         { "SHIFT_JIS", RTL_TEXTENCODING_SHIFT_JIS },
    1140             :         { "MS_KANJI", RTL_TEXTENCODING_SHIFT_JIS },
    1141             :         { "CSSHIFTJIS", RTL_TEXTENCODING_SHIFT_JIS },
    1142             :         { "GB2312", RTL_TEXTENCODING_GB_2312 },
    1143             :         { "CSGB2312", RTL_TEXTENCODING_GB_2312 },
    1144             :         { "BIG5", RTL_TEXTENCODING_BIG5 },
    1145             :         { "CSBIG5", RTL_TEXTENCODING_BIG5 },
    1146             :         { "EUC-JP", RTL_TEXTENCODING_EUC_JP },
    1147             :         { "EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE",
    1148             :           RTL_TEXTENCODING_EUC_JP },
    1149             :         { "CSEUCPKDFMTJAPANESE", RTL_TEXTENCODING_EUC_JP },
    1150             :         { "ISO-2022-JP", RTL_TEXTENCODING_ISO_2022_JP },
    1151             :         { "CSISO2022JP", RTL_TEXTENCODING_ISO_2022_JP },
    1152             :         { "ISO-2022-CN", RTL_TEXTENCODING_ISO_2022_CN },
    1153             :         { "KOI8-R", RTL_TEXTENCODING_KOI8_R },
    1154             :         { "CSKOI8R", RTL_TEXTENCODING_KOI8_R },
    1155             :         { "UTF-7", RTL_TEXTENCODING_UTF7 },
    1156             :         { "UTF-8", RTL_TEXTENCODING_UTF8 },
    1157             :         { "ISO-8859-10", RTL_TEXTENCODING_ISO_8859_10 }, // RFC 2047
    1158             :         { "ISO-8859-13", RTL_TEXTENCODING_ISO_8859_13 }, // RFC 2047
    1159             :         { "EUC-KR", RTL_TEXTENCODING_EUC_KR },
    1160             :         { "CSEUCKR", RTL_TEXTENCODING_EUC_KR },
    1161             :         { "ISO-2022-KR", RTL_TEXTENCODING_ISO_2022_KR },
    1162             :         { "CSISO2022KR", RTL_TEXTENCODING_ISO_2022_KR },
    1163             :         { "ISO-10646-UCS-4", RTL_TEXTENCODING_UCS4 },
    1164             :         { "CSUCS4", RTL_TEXTENCODING_UCS4 },
    1165             :         { "ISO-10646-UCS-2", RTL_TEXTENCODING_UCS2 },
    1166             :         { "CSUNICODE", RTL_TEXTENCODING_UCS2 } };
    1167             : 
    1168             : template< typename T >
    1169           3 : inline rtl_TextEncoding getCharsetEncoding_Impl(T const * pBegin,
    1170             :                                                 T const * pEnd)
    1171             : {
    1172          36 :     for (sal_Size i = 0; i < sizeof aEncodingMap / sizeof (EncodingEntry);
    1173             :          ++i)
    1174          36 :         if (INetMIME::equalIgnoreCase(pBegin, pEnd, aEncodingMap[i].m_aName))
    1175           3 :             return aEncodingMap[i].m_eEncoding;
    1176           0 :     return RTL_TEXTENCODING_DONTKNOW;
    1177             : }
    1178             : 
    1179             : }
    1180             : 
    1181             : // static
    1182           3 : rtl_TextEncoding INetMIME::getCharsetEncoding(sal_Char const * pBegin,
    1183             :                                               sal_Char const * pEnd)
    1184             : {
    1185           3 :     return getCharsetEncoding_Impl(pBegin, pEnd);
    1186             : }
    1187             : 
    1188             : // static
    1189             : INetMIMECharsetList_Impl *
    1190           0 : INetMIME::createPreferredCharsetList(rtl_TextEncoding eEncoding)
    1191             : {
    1192             :     static const sal_uInt32 aUSASCIIRanges[] = { 0, 0x7F, sal_uInt32(-1) };
    1193             : 
    1194             :     static const sal_uInt32 aISO88591Ranges[] = { 0, 0xFF, sal_uInt32(-1) };
    1195             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-1.TXT> version
    1196             :         // 1.0 of 1999 July 27
    1197             : 
    1198             :     static const sal_uInt32 aISO88592Ranges[]
    1199             :         = { 0, 0xA0, 0xA4, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xB0, 0xB0,
    1200             :             0xB4, 0xB4, 0xB8, 0xB8, 0xC1, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7,
    1201             :             0xC9, 0xC9, 0xCB, 0xCB, 0xCD, 0xCE, 0xD3, 0xD4, 0xD6, 0xD7,
    1202             :             0xDA, 0xDA, 0xDC, 0xDD, 0xDF, 0xDF, 0xE1, 0xE2, 0xE4, 0xE4,
    1203             :             0xE7, 0xE7, 0xE9, 0xE9, 0xEB, 0xEB, 0xED, 0xEE, 0xF3, 0xF4,
    1204             :             0xF6, 0xF7, 0xFA, 0xFA, 0xFC, 0xFD, 0x102, 0x107, 0x10C, 0x111,
    1205             :             0x118, 0x11B, 0x139, 0x13A, 0x13D, 0x13E, 0x141, 0x144,
    1206             :             0x147, 0x148, 0x150, 0x151, 0x154, 0x155, 0x158, 0x15B,
    1207             :             0x15E, 0x165, 0x16E, 0x171, 0x179, 0x17E, 0x2C7, 0x2C7,
    1208             :             0x2D8, 0x2D9, 0x2DB, 0x2DB, 0x2DD, 0x2DD, sal_uInt32(-1) };
    1209             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-2.TXT> version
    1210             :         // 1.0 of 1999 July 27
    1211             : 
    1212             :     static const sal_uInt32 aISO88593Ranges[]
    1213             :         = { 0, 0xA0, 0xA3, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xB0, 0xB0,
    1214             :             0xB2, 0xB5, 0xB7, 0xB8, 0xBD, 0xBD, 0xC0, 0xC2, 0xC4, 0xC4,
    1215             :             0xC7, 0xCF, 0xD1, 0xD4, 0xD6, 0xD7, 0xD9, 0xDC, 0xDF, 0xE2,
    1216             :             0xE4, 0xE4, 0xE7, 0xEF, 0xF1, 0xF4, 0xF6, 0xF7, 0xF9, 0xFC,
    1217             :             0x108, 0x10B, 0x11C, 0x121, 0x124, 0x127, 0x130, 0x131,
    1218             :             0x134, 0x135, 0x15C, 0x15F, 0x16C, 0x16D, 0x17B, 0x17C,
    1219             :             0x2D8, 0x2D9, sal_uInt32(-1) };
    1220             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-3.TXT> version
    1221             :         // 1.0 of 1999 July 27
    1222             : 
    1223             :     static const sal_uInt32 aISO88594Ranges[]
    1224             :         = { 0, 0xA0, 0xA4, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xAF, 0xB0,
    1225             :             0xB4, 0xB4, 0xB8, 0xB8, 0xC1, 0xC6, 0xC9, 0xC9, 0xCB, 0xCB,
    1226             :             0xCD, 0xCE, 0xD4, 0xD8, 0xDA, 0xDC, 0xDF, 0xDF, 0xE1, 0xE6,
    1227             :             0xE9, 0xE9, 0xEB, 0xEB, 0xED, 0xEE, 0xF4, 0xF8, 0xFA, 0xFC,
    1228             :             0x100, 0x101, 0x104, 0x105, 0x10C, 0x10D, 0x110, 0x113,
    1229             :             0x116, 0x119, 0x122, 0x123, 0x128, 0x12B, 0x12E, 0x12F,
    1230             :             0x136, 0x138, 0x13B, 0x13C, 0x145, 0x146, 0x14A, 0x14D,
    1231             :             0x156, 0x157, 0x160, 0x161, 0x166, 0x16B, 0x172, 0x173,
    1232             :             0x17D, 0x17E, 0x2C7, 0x2C7, 0x2D9, 0x2D9, 0x2DB, 0x2DB,
    1233             :             sal_uInt32(-1) };
    1234             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-4.TXT> version
    1235             :         // 1.0 of 1999 July 27
    1236             : 
    1237             :     static const sal_uInt32 aISO88595Ranges[]
    1238             :         = { 0, 0xA0, 0xA7, 0xA7, 0xAD, 0xAD, 0x401, 0x40C, 0x40E, 0x44F,
    1239             :             0x451, 0x45C, 0x45E, 0x45F, 0x2116, 0x2116, sal_uInt32(-1) };
    1240             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-5.TXT> version
    1241             :         // 1.0 of 1999 July 27
    1242             : 
    1243             :     static const sal_uInt32 aISO88596Ranges[]
    1244             :         = { 0, 0xA0, 0xA4, 0xA4, 0xAD, 0xAD, 0x60C, 0x60C, 0x61B, 0x61B,
    1245             :             0x61F, 0x61F, 0x621, 0x63A, 0x640, 0x652, sal_uInt32(-1) };
    1246             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-6.TXT> version
    1247             :         // 1.0 of 1999 July 27
    1248             : 
    1249             :     static const sal_uInt32 aISO88597Ranges[]
    1250             :         = { 0, 0xA0, 0xA3, 0xA3, 0xA6, 0xA9, 0xAB, 0xAD, 0xB0, 0xB3,
    1251             :             0xB7, 0xB7, 0xBB, 0xBB, 0xBD, 0xBD, 0x384, 0x386, 0x388, 0x38A,
    1252             :             0x38C, 0x38C, 0x38E, 0x3A1, 0x3A3, 0x3CE, 0x2015, 0x2015,
    1253             :             0x2018, 0x2019, sal_uInt32(-1) };
    1254             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-7.TXT> version
    1255             :         // 1.0 of 1999 July 27
    1256             : 
    1257             :     static const sal_uInt32 aISO88598Ranges[]
    1258             :         = { 0, 0xA0, 0xA2, 0xA9, 0xAB, 0xB9, 0xBB, 0xBE, 0xD7, 0xD7,
    1259             :             0xF7, 0xF7, 0x5D0, 0x5EA, 0x200E, 0x200F, 0x2017, 0x2017,
    1260             :             sal_uInt32(-1) };
    1261             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-8.TXT> version
    1262             :         // 1.1 of 2000-Jan-03
    1263             : 
    1264             :     static const sal_uInt32 aISO88599Ranges[]
    1265             :         = { 0, 0xCF, 0xD1, 0xDC, 0xDF, 0xEF, 0xF1, 0xFC, 0xFF, 0xFF,
    1266             :             0x11E, 0x11F, 0x130, 0x131, 0x15E, 0x15F, sal_uInt32(-1) };
    1267             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-9.TXT> version
    1268             :         // 1.0 of 1999 July 27
    1269             : 
    1270             :     static const sal_uInt32 aISO885910Ranges[]
    1271             :         = { 0, 0xA0, 0xA7, 0xA7, 0xAD, 0xAD, 0xB0, 0xB0, 0xB7, 0xB7,
    1272             :             0xC1, 0xC6, 0xC9, 0xC9, 0xCB, 0xCB, 0xCD, 0xD0, 0xD3, 0xD6,
    1273             :             0xD8, 0xD8, 0xDA, 0xDF, 0xE1, 0xE6, 0xE9, 0xE9, 0xEB, 0xEB,
    1274             :             0xED, 0xF0, 0xF3, 0xF6, 0xF8, 0xF8, 0xFA, 0xFE, 0x100, 0x101,
    1275             :             0x104, 0x105, 0x10C, 0x10D, 0x110, 0x113, 0x116, 0x119,
    1276             :             0x122, 0x123, 0x128, 0x12B, 0x12E, 0x12F, 0x136, 0x138,
    1277             :             0x13B, 0x13C, 0x145, 0x146, 0x14A, 0x14D, 0x160, 0x161,
    1278             :             0x166, 0x16B, 0x172, 0x173, 0x17D, 0x17E, 0x2015, 0x2015,
    1279             :             sal_uInt32(-1) };
    1280             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-10.TXT> version
    1281             :         // 1.1 of 1999 October 11
    1282             : 
    1283             :     static const sal_uInt32 aISO885913Ranges[]
    1284             :         = { 0, 0xA0, 0xA2, 0xA4, 0xA6, 0xA7, 0xA9, 0xA9, 0xAB, 0xAE,
    1285             :             0xB0, 0xB3, 0xB5, 0xB7, 0xB9, 0xB9, 0xBB, 0xBE, 0xC4, 0xC6,
    1286             :             0xC9, 0xC9, 0xD3, 0xD3, 0xD5, 0xD8, 0xDC, 0xDC, 0xDF, 0xDF,
    1287             :             0xE4, 0xE6, 0xE9, 0xE9, 0xF3, 0xF3, 0xF5, 0xF8, 0xFC, 0xFC,
    1288             :             0x100, 0x101, 0x104, 0x107, 0x10C, 0x10D, 0x112, 0x113,
    1289             :             0x116, 0x119, 0x122, 0x123, 0x12A, 0x12B, 0x12E, 0x12F,
    1290             :             0x136, 0x137, 0x13B, 0x13C, 0x141, 0x146, 0x14C, 0x14D,
    1291             :             0x156, 0x157, 0x15A, 0x15B, 0x160, 0x161, 0x16A, 0x16B,
    1292             :             0x172, 0x173, 0x179, 0x17E, 0x2019, 0x2019, 0x201C, 0x201E,
    1293             :             sal_uInt32(-1) };
    1294             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-13.TXT> version
    1295             :         // 1.0 of 1999 July 27
    1296             : 
    1297             :     static const sal_uInt32 aISO885914Ranges[]
    1298             :         = { 0, 0xA0, 0xA3, 0xA3, 0xA7, 0xA7, 0xA9, 0xA9, 0xAD, 0xAE,
    1299             :             0xB6, 0xB6, 0xC0, 0xCF, 0xD1, 0xD6, 0xD8, 0xDD, 0xDF, 0xEF,
    1300             :             0xF1, 0xF6, 0xF8, 0xFD, 0xFF, 0xFF, 0x10A, 0x10B, 0x120, 0x121,
    1301             :             0x174, 0x178, 0x1E02, 0x1E03, 0x1E0A, 0x1E0B, 0x1E1E, 0x1E1F,
    1302             :             0x1E40, 0x1E41, 0x1E56, 0x1E57, 0x1E60, 0x1E61, 0x1E6A, 0x1E6B,
    1303             :             0x1E80, 0x1E85, 0x1EF2, 0x1EF3, sal_uInt32(-1) };
    1304             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-14.TXT> version
    1305             :         // 1.0 of 1999 July 27
    1306             : 
    1307             :     static const sal_uInt32 aISO885915Ranges[]
    1308             :         = { 0, 0xA3, 0xA5, 0xA5, 0xA7, 0xA7, 0xA9, 0xB3, 0xB5, 0xB7,
    1309             :             0xB9, 0xBB, 0xBF, 0xFF, 0x152, 0x153, 0x160, 0x161, 0x178, 0x178,
    1310             :             0x17D, 0x17E, 0x20AC, 0x20AC, sal_uInt32(-1) };
    1311             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-15.TXT> version
    1312             :         // 1.0 of 1999 July 27
    1313             : 
    1314             :     static const sal_uInt32 aKOI8RRanges[]
    1315             :         = { 0, 0x7F, 0xA0, 0xA0, 0xA9, 0xA9, 0xB0, 0xB0, 0xB2, 0xB2,
    1316             :             0xB7, 0xB7, 0xF7, 0xF7, 0x401, 0x401, 0x410, 0x44F, 0x451, 0x451,
    1317             :             0x2219, 0x221A, 0x2248, 0x2248, 0x2264, 0x2265, 0x2320, 0x2321,
    1318             :             0x2500, 0x2500, 0x2502, 0x2502, 0x250C, 0x250C, 0x2510, 0x2510,
    1319             :             0x2514, 0x2514, 0x2518, 0x2518, 0x251C, 0x251C, 0x2524, 0x2524,
    1320             :             0x252C, 0x252C, 0x2534, 0x2534, 0x253C, 0x253C, 0x2550, 0x256C,
    1321             :             0x2580, 0x2580, 0x2584, 0x2584, 0x2588, 0x2588, 0x258C, 0x258C,
    1322             :             0x2590, 0x2593, 0x25A0, 0x25A0, sal_uInt32(-1) };
    1323             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MISC/KOI8-R.TXT>
    1324             :         // version 1.0 of 18 August 1999
    1325             : 
    1326             : #if defined WNT
    1327             :     static const sal_uInt32 aWindows1252Ranges[]
    1328             :         = { 0, 0x7F, 0xA0, 0xFF, 0x152, 0x153, 0x160, 0x161, 0x178, 0x178,
    1329             :             0x17D, 0x17E, 0x192, 0x192, 0x2C6, 0x2C6, 0x2DC, 0x2DC,
    1330             :             0x2013, 0x2014, 0x2018, 0x201A, 0x201C, 0x201E, 0x2020, 0x2022,
    1331             :             0x2026, 0x2026, 0x2030, 0x2030, 0x2039, 0x203A, 0x20AC, 0x20AC,
    1332             :             0x2122, 0x2122, sal_uInt32(-1) };
    1333             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/
    1334             :         // CP1252.TXT> version 2.01 of 04/15/98
    1335             : #endif // WNT
    1336             : 
    1337           0 :     INetMIMECharsetList_Impl * pList = new INetMIMECharsetList_Impl;
    1338           0 :     switch (eEncoding)
    1339             :     {
    1340             :         case RTL_TEXTENCODING_MS_1252:
    1341             : #if defined WNT
    1342             :             pList->prepend(Charset(RTL_TEXTENCODING_MS_1252,
    1343             :                                    aWindows1252Ranges));
    1344             : #endif // WNT
    1345             :         case RTL_TEXTENCODING_ISO_8859_1:
    1346             :         case RTL_TEXTENCODING_UTF7:
    1347             :         case RTL_TEXTENCODING_UTF8:
    1348           0 :             break;
    1349             : 
    1350             :         case RTL_TEXTENCODING_ISO_8859_2:
    1351             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_2,
    1352           0 :                                    aISO88592Ranges));
    1353           0 :             break;
    1354             : 
    1355             :         case RTL_TEXTENCODING_ISO_8859_3:
    1356             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_3,
    1357           0 :                                    aISO88593Ranges));
    1358           0 :             break;
    1359             : 
    1360             :         case RTL_TEXTENCODING_ISO_8859_4:
    1361             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_4,
    1362           0 :                                    aISO88594Ranges));
    1363           0 :             break;
    1364             : 
    1365             :         case RTL_TEXTENCODING_ISO_8859_5:
    1366             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5,
    1367           0 :                                    aISO88595Ranges));
    1368           0 :             break;
    1369             : 
    1370             :         case RTL_TEXTENCODING_ISO_8859_6:
    1371             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_6,
    1372           0 :                                    aISO88596Ranges));
    1373           0 :             break;
    1374             : 
    1375             :         case RTL_TEXTENCODING_ISO_8859_7:
    1376             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_7,
    1377           0 :                                    aISO88597Ranges));
    1378           0 :             break;
    1379             : 
    1380             :         case RTL_TEXTENCODING_ISO_8859_8:
    1381             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_8,
    1382           0 :                                    aISO88598Ranges));
    1383           0 :             break;
    1384             : 
    1385             :         case RTL_TEXTENCODING_ISO_8859_9:
    1386             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_9,
    1387           0 :                                    aISO88599Ranges));
    1388           0 :             break;
    1389             : 
    1390             :         case RTL_TEXTENCODING_ISO_8859_10:
    1391             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_10,
    1392           0 :                                    aISO885910Ranges));
    1393           0 :             break;
    1394             : 
    1395             :         case RTL_TEXTENCODING_ISO_8859_13:
    1396             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_13,
    1397           0 :                                    aISO885913Ranges));
    1398           0 :             break;
    1399             : 
    1400             :         case RTL_TEXTENCODING_ISO_8859_14:
    1401             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_14,
    1402           0 :                                    aISO885914Ranges));
    1403           0 :             break;
    1404             : 
    1405             :         case RTL_TEXTENCODING_ISO_8859_15:
    1406             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_15,
    1407           0 :                                    aISO885915Ranges));
    1408           0 :             break;
    1409             : 
    1410             :         case RTL_TEXTENCODING_MS_1250:
    1411             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_2,
    1412           0 :                                    aISO88592Ranges));
    1413           0 :             break;
    1414             : 
    1415             :         case RTL_TEXTENCODING_MS_1251:
    1416             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5,
    1417           0 :                                    aISO88595Ranges));
    1418           0 :             break;
    1419             : 
    1420             :         case RTL_TEXTENCODING_MS_1253:
    1421             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_7,
    1422           0 :                                    aISO88597Ranges));
    1423           0 :             break;
    1424             : 
    1425             :         case RTL_TEXTENCODING_MS_1254:
    1426             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_9,
    1427           0 :                                    aISO88599Ranges));
    1428           0 :             break;
    1429             : 
    1430             :         case RTL_TEXTENCODING_MS_1255:
    1431             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_8,
    1432           0 :                                    aISO88598Ranges));
    1433           0 :             break;
    1434             : 
    1435             :         case RTL_TEXTENCODING_MS_1256:
    1436             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_6,
    1437           0 :                                    aISO88596Ranges));
    1438           0 :             break;
    1439             : 
    1440             :         case RTL_TEXTENCODING_MS_1257:
    1441             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_4,
    1442           0 :                                    aISO88594Ranges));
    1443           0 :             break;
    1444             : 
    1445             :         case RTL_TEXTENCODING_KOI8_R:
    1446             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5,
    1447           0 :                                    aISO88595Ranges));
    1448           0 :             pList->prepend(Charset(RTL_TEXTENCODING_KOI8_R, aKOI8RRanges));
    1449           0 :             break;
    1450             : 
    1451             :         default: //@@@ more cases are missing!
    1452             :             OSL_FAIL("INetMIME::createPreferredCharsetList():"
    1453             :                           " Unsupported encoding");
    1454           0 :             break;
    1455             :     }
    1456           0 :     pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_1, aISO88591Ranges));
    1457           0 :     pList->prepend(Charset(RTL_TEXTENCODING_ASCII_US, aUSASCIIRanges));
    1458           0 :     return pList;
    1459             : }
    1460             : 
    1461             : // static
    1462           3 : sal_Unicode * INetMIME::convertToUnicode(const sal_Char * pBegin,
    1463             :                                          const sal_Char * pEnd,
    1464             :                                          rtl_TextEncoding eEncoding,
    1465             :                                          sal_Size & rSize)
    1466             : {
    1467           3 :     if (eEncoding == RTL_TEXTENCODING_DONTKNOW)
    1468           0 :         return 0;
    1469             :     rtl_TextToUnicodeConverter hConverter
    1470           3 :         = rtl_createTextToUnicodeConverter(eEncoding);
    1471             :     rtl_TextToUnicodeContext hContext
    1472           3 :         = rtl_createTextToUnicodeContext(hConverter);
    1473             :     sal_Unicode * pBuffer;
    1474             :     sal_uInt32 nInfo;
    1475           3 :     for (sal_Size nBufferSize = pEnd - pBegin;;
    1476             :          nBufferSize += nBufferSize / 3 + 1)
    1477             :     {
    1478           3 :         pBuffer = new sal_Unicode[nBufferSize];
    1479             :         sal_Size nSrcCvtBytes;
    1480             :         rSize = rtl_convertTextToUnicode(
    1481             :                     hConverter, hContext, pBegin, pEnd - pBegin, pBuffer,
    1482             :                     nBufferSize,
    1483             :                     RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
    1484             :                         | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
    1485             :                         | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
    1486           3 :                     &nInfo, &nSrcCvtBytes);
    1487           3 :         if (nInfo != RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL)
    1488             :             break;
    1489           0 :         delete[] pBuffer;
    1490           0 :         rtl_resetTextToUnicodeContext(hConverter, hContext);
    1491             :     }
    1492           3 :     rtl_destroyTextToUnicodeContext(hConverter, hContext);
    1493           3 :     rtl_destroyTextToUnicodeConverter(hConverter);
    1494           3 :     if (nInfo != 0)
    1495             :     {
    1496           0 :         delete[] pBuffer;
    1497           0 :         pBuffer = 0;
    1498             :     }
    1499           3 :     return pBuffer;
    1500             : }
    1501             : 
    1502             : // static
    1503           0 : sal_Char * INetMIME::convertFromUnicode(const sal_Unicode * pBegin,
    1504             :                                         const sal_Unicode * pEnd,
    1505             :                                         rtl_TextEncoding eEncoding,
    1506             :                                         sal_Size & rSize)
    1507             : {
    1508           0 :     if (eEncoding == RTL_TEXTENCODING_DONTKNOW)
    1509           0 :         return 0;
    1510             :     rtl_UnicodeToTextConverter hConverter
    1511           0 :         = rtl_createUnicodeToTextConverter(eEncoding);
    1512             :     rtl_UnicodeToTextContext hContext
    1513           0 :         = rtl_createUnicodeToTextContext(hConverter);
    1514             :     sal_Char * pBuffer;
    1515             :     sal_uInt32 nInfo;
    1516           0 :     for (sal_Size nBufferSize = pEnd - pBegin;;
    1517             :          nBufferSize += nBufferSize / 3 + 1)
    1518             :     {
    1519           0 :         pBuffer = new sal_Char[nBufferSize];
    1520             :         sal_Size nSrcCvtBytes;
    1521             :         rSize = rtl_convertUnicodeToText(
    1522             :                     hConverter, hContext, pBegin, pEnd - pBegin, pBuffer,
    1523             :                     nBufferSize,
    1524             :                     RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
    1525             :                         | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
    1526             :                         | RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE
    1527             :                         | RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACESTR,
    1528           0 :                     &nInfo, &nSrcCvtBytes);
    1529           0 :         if (nInfo != RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL)
    1530             :             break;
    1531           0 :         delete[] pBuffer;
    1532           0 :         rtl_resetUnicodeToTextContext(hConverter, hContext);
    1533             :     }
    1534           0 :     rtl_destroyUnicodeToTextContext(hConverter, hContext);
    1535           0 :     rtl_destroyUnicodeToTextConverter(hConverter);
    1536           0 :     if (nInfo != 0)
    1537             :     {
    1538           0 :         delete[] pBuffer;
    1539           0 :         pBuffer = 0;
    1540             :     }
    1541           0 :     return pBuffer;
    1542             : }
    1543             : 
    1544             : // static
    1545           0 : void INetMIME::writeUTF8(INetMIMEOutputSink & rSink, sal_uInt32 nChar)
    1546             : {
    1547             :     // See RFC 2279 for a discussion of UTF-8.
    1548             :     DBG_ASSERT(nChar < 0x80000000, "INetMIME::writeUTF8(): Bad char");
    1549             : 
    1550           0 :     if (nChar < 0x80)
    1551           0 :         rSink << sal_Char(nChar);
    1552           0 :     else if (nChar < 0x800)
    1553           0 :         rSink << sal_Char(nChar >> 6 | 0xC0)
    1554           0 :               << sal_Char((nChar & 0x3F) | 0x80);
    1555           0 :     else if (nChar < 0x10000)
    1556           0 :         rSink << sal_Char(nChar >> 12 | 0xE0)
    1557           0 :               << sal_Char((nChar >> 6 & 0x3F) | 0x80)
    1558           0 :               << sal_Char((nChar & 0x3F) | 0x80);
    1559           0 :     else if (nChar < 0x200000)
    1560           0 :         rSink << sal_Char(nChar >> 18 | 0xF0)
    1561           0 :               << sal_Char((nChar >> 12 & 0x3F) | 0x80)
    1562           0 :               << sal_Char((nChar >> 6 & 0x3F) | 0x80)
    1563           0 :               << sal_Char((nChar & 0x3F) | 0x80);
    1564           0 :     else if (nChar < 0x4000000)
    1565           0 :         rSink << sal_Char(nChar >> 24 | 0xF8)
    1566           0 :               << sal_Char((nChar >> 18 & 0x3F) | 0x80)
    1567           0 :               << sal_Char((nChar >> 12 & 0x3F) | 0x80)
    1568           0 :               << sal_Char((nChar >> 6 & 0x3F) | 0x80)
    1569           0 :               << sal_Char((nChar & 0x3F) | 0x80);
    1570             :     else
    1571           0 :         rSink << sal_Char(nChar >> 30 | 0xFC)
    1572           0 :               << sal_Char((nChar >> 24 & 0x3F) | 0x80)
    1573           0 :               << sal_Char((nChar >> 18 & 0x3F) | 0x80)
    1574           0 :               << sal_Char((nChar >> 12 & 0x3F) | 0x80)
    1575           0 :               << sal_Char((nChar >> 6 & 0x3F) | 0x80)
    1576           0 :               << sal_Char((nChar & 0x3F) | 0x80);
    1577           0 : }
    1578             : 
    1579             : // static
    1580           0 : void INetMIME::writeHeaderFieldBody(INetMIMEOutputSink & rSink,
    1581             :                                     HeaderFieldType eType,
    1582             :                                     const rtl::OUString& rBody,
    1583             :                                     rtl_TextEncoding ePreferredEncoding,
    1584             :                                     bool bInitialSpace)
    1585             : {
    1586           0 :     if (eType == HEADER_FIELD_TEXT)
    1587             :     {
    1588             :         INetMIMEEncodedWordOutputSink
    1589             :             aOutput(rSink, INetMIMEEncodedWordOutputSink::CONTEXT_TEXT,
    1590             :                     bInitialSpace ?
    1591             :                         INetMIMEEncodedWordOutputSink::SPACE_ALWAYS :
    1592             :                         INetMIMEEncodedWordOutputSink::SPACE_NO,
    1593           0 :                     ePreferredEncoding);
    1594           0 :         aOutput.write(rBody.getStr(), rBody.getStr() + rBody.getLength());
    1595           0 :         aOutput.flush();
    1596             :     }
    1597             :     else
    1598             :     {
    1599             :         enum Brackets { BRACKETS_OUTSIDE, BRACKETS_OPENING, BRACKETS_INSIDE };
    1600           0 :         Brackets eBrackets = BRACKETS_OUTSIDE;
    1601             : 
    1602           0 :         const sal_Unicode * pBodyPtr = rBody.getStr();
    1603           0 :         const sal_Unicode * pBodyEnd = pBodyPtr + rBody.getLength();
    1604           0 :         while (pBodyPtr != pBodyEnd)
    1605           0 :             switch (*pBodyPtr)
    1606             :             {
    1607             :                 case '\t':
    1608             :                 case ' ':
    1609             :                     // A WSP adds to accumulated space:
    1610           0 :                     bInitialSpace = true;
    1611           0 :                     ++pBodyPtr;
    1612           0 :                     break;
    1613             : 
    1614             :                 case '(':
    1615             :                 {
    1616             :                     // Write a pending '<' if necessary:
    1617           0 :                     if (eBrackets == BRACKETS_OPENING)
    1618             :                     {
    1619           0 :                         if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1620           0 :                                 >= rSink.getLineLengthLimit())
    1621           0 :                             rSink << INetMIMEOutputSink::endl << ' ';
    1622           0 :                         else if (bInitialSpace)
    1623           0 :                             rSink << ' ';
    1624           0 :                         rSink << '<';
    1625           0 :                         bInitialSpace = false;
    1626           0 :                         eBrackets = BRACKETS_INSIDE;
    1627             :                     }
    1628             : 
    1629             :                     // Write the comment, introducing encoded-words where
    1630             :                     // necessary:
    1631           0 :                     int nLevel = 0;
    1632             :                     INetMIMEEncodedWordOutputSink
    1633             :                         aOutput(
    1634             :                             rSink,
    1635             :                             INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT,
    1636             :                             INetMIMEEncodedWordOutputSink::SPACE_NO,
    1637           0 :                             ePreferredEncoding);
    1638           0 :                     while (pBodyPtr != pBodyEnd)
    1639           0 :                         switch (*pBodyPtr)
    1640             :                         {
    1641             :                             case '(':
    1642           0 :                                 aOutput.flush();
    1643           0 :                                 if (rSink.getColumn()
    1644             :                                             + (bInitialSpace ? 1 : 0)
    1645           0 :                                         >= rSink.getLineLengthLimit())
    1646           0 :                                     rSink << INetMIMEOutputSink::endl << ' ';
    1647           0 :                                 else if (bInitialSpace)
    1648           0 :                                     rSink << ' ';
    1649           0 :                                 rSink << '(';
    1650           0 :                                 bInitialSpace = false;
    1651           0 :                                 ++nLevel;
    1652           0 :                                 ++pBodyPtr;
    1653           0 :                                 break;
    1654             : 
    1655             :                             case ')':
    1656           0 :                                 aOutput.flush();
    1657           0 :                                 if (rSink.getColumn()
    1658           0 :                                         >= rSink.getLineLengthLimit())
    1659           0 :                                     rSink << INetMIMEOutputSink::endl << ' ';
    1660           0 :                                 rSink << ')';
    1661           0 :                                 ++pBodyPtr;
    1662           0 :                                 if (--nLevel == 0)
    1663           0 :                                     goto comment_done;
    1664           0 :                                 break;
    1665             : 
    1666             :                             case '\\':
    1667           0 :                                 if (++pBodyPtr == pBodyEnd)
    1668           0 :                                     break;
    1669             :                             default:
    1670           0 :                                 aOutput << *pBodyPtr++;
    1671           0 :                                 break;
    1672             :                         }
    1673             :                 comment_done:
    1674           0 :                     break;
    1675             :                 }
    1676             : 
    1677             :                 case '<':
    1678             :                     // Write an already pending '<' if necessary:
    1679           0 :                     if (eBrackets == BRACKETS_OPENING)
    1680             :                     {
    1681           0 :                         if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1682           0 :                                 >= rSink.getLineLengthLimit())
    1683           0 :                             rSink << INetMIMEOutputSink::endl << ' ';
    1684           0 :                         else if (bInitialSpace)
    1685           0 :                             rSink << ' ';
    1686           0 :                         rSink << '<';
    1687           0 :                         bInitialSpace = false;
    1688             :                     }
    1689             : 
    1690             :                     // Remember this '<' as pending, and open a bracketed
    1691             :                     // block:
    1692           0 :                     eBrackets = BRACKETS_OPENING;
    1693           0 :                     ++pBodyPtr;
    1694           0 :                     break;
    1695             : 
    1696             :                 case '>':
    1697             :                     // Write a pending '<' if necessary:
    1698           0 :                     if (eBrackets == BRACKETS_OPENING)
    1699             :                     {
    1700           0 :                         if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1701           0 :                                 >= rSink.getLineLengthLimit())
    1702           0 :                             rSink << INetMIMEOutputSink::endl << ' ';
    1703           0 :                         else if (bInitialSpace)
    1704           0 :                             rSink << ' ';
    1705           0 :                         rSink << '<';
    1706           0 :                         bInitialSpace = false;
    1707             :                     }
    1708             : 
    1709             :                     // Write this '>', and close any bracketed block:
    1710           0 :                     if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1711           0 :                             >= rSink.getLineLengthLimit())
    1712           0 :                         rSink << INetMIMEOutputSink::endl << ' ';
    1713           0 :                     else if (bInitialSpace)
    1714           0 :                         rSink << ' ';
    1715           0 :                     rSink << '>';
    1716           0 :                     bInitialSpace = false;
    1717           0 :                     eBrackets = BRACKETS_OUTSIDE;
    1718           0 :                     ++pBodyPtr;
    1719           0 :                     break;
    1720             : 
    1721             :                 case ',':
    1722             :                 case ':':
    1723             :                 case ';':
    1724             :                 case '\\':
    1725             :                 case ']':
    1726             :                     // Write a pending '<' if necessary:
    1727           0 :                     if (eBrackets == BRACKETS_OPENING)
    1728             :                     {
    1729           0 :                         if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1730           0 :                                 >= rSink.getLineLengthLimit())
    1731           0 :                             rSink << INetMIMEOutputSink::endl << ' ';
    1732           0 :                         else if (bInitialSpace)
    1733           0 :                             rSink << ' ';
    1734           0 :                         rSink << '<';
    1735           0 :                         bInitialSpace = false;
    1736           0 :                         eBrackets = BRACKETS_INSIDE;
    1737             :                     }
    1738             : 
    1739             :                     // Write this specials:
    1740           0 :                     if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1741           0 :                             >= rSink.getLineLengthLimit())
    1742           0 :                         rSink << INetMIMEOutputSink::endl << ' ';
    1743           0 :                     else if (bInitialSpace)
    1744           0 :                         rSink << ' ';
    1745           0 :                     rSink << sal_Char(*pBodyPtr++);
    1746           0 :                     bInitialSpace = false;
    1747           0 :                     break;
    1748             : 
    1749             :                 case '\x0D': // CR
    1750             :                     // A <CRLF WSP> adds to accumulated space, a <CR> not
    1751             :                     // followed by <LF WSP> starts 'junk':
    1752           0 :                     if (startsWithLineFolding(pBodyPtr, pBodyEnd))
    1753             :                     {
    1754           0 :                         bInitialSpace = true;
    1755           0 :                         pBodyPtr += 3;
    1756           0 :                         break;
    1757             :                     }
    1758             :                 default:
    1759             :                 {
    1760             :                     // The next token is either one of <"." / "@" / atom /
    1761             :                     // quoted-string / domain-literal>, or it's 'junk'; if it
    1762             :                     // is not 'junk', it is either a 'phrase' (i.e., it may
    1763             :                     // contain encoded-words) or a 'non-phrase' (i.e., it may
    1764             :                     // not contain encoded-words):
    1765             :                     enum Entity { ENTITY_JUNK, ENTITY_NON_PHRASE,
    1766             :                                   ENTITY_PHRASE };
    1767           0 :                     Entity eEntity = ENTITY_JUNK;
    1768           0 :                     switch (*pBodyPtr)
    1769             :                     {
    1770             :                         case '.':
    1771             :                         case '@':
    1772             :                         case '[':
    1773             :                             // A token of <"." / "@" / domain-literal> always
    1774             :                             // starts a 'non-phrase':
    1775           0 :                             eEntity = ENTITY_NON_PHRASE;
    1776           0 :                             break;
    1777             : 
    1778             :                         default:
    1779           0 :                             if (isUSASCII(*pBodyPtr)
    1780           0 :                                 && !isAtomChar(*pBodyPtr))
    1781             :                             {
    1782           0 :                                 eEntity = ENTITY_JUNK;
    1783           0 :                                 break;
    1784             :                             }
    1785             :                         case '"':
    1786             :                             // A token of <atom / quoted-string> can either be
    1787             :                             // a 'phrase' or a 'non-phrase':
    1788           0 :                             switch (eType)
    1789             :                             {
    1790             :                                 case HEADER_FIELD_STRUCTURED:
    1791           0 :                                     eEntity = ENTITY_NON_PHRASE;
    1792           0 :                                     break;
    1793             : 
    1794             :                                 case HEADER_FIELD_PHRASE:
    1795           0 :                                     eEntity = ENTITY_PHRASE;
    1796           0 :                                     break;
    1797             : 
    1798             :                                 case HEADER_FIELD_MESSAGE_ID:
    1799             :                                     // A 'phrase' if and only if outside any
    1800             :                                     // bracketed block:
    1801             :                                     eEntity
    1802             :                                         = eBrackets == BRACKETS_OUTSIDE ?
    1803             :                                               ENTITY_PHRASE :
    1804           0 :                                               ENTITY_NON_PHRASE;
    1805           0 :                                     break;
    1806             : 
    1807             :                                 case HEADER_FIELD_ADDRESS:
    1808             :                                 {
    1809             :                                     // A 'non-phrase' if and only if, after
    1810             :                                     // skipping this token and any following
    1811             :                                     // <linear-white-space> and <comment>s,
    1812             :                                     // there is no token left, or the next
    1813             :                                     // token is any of <"." / "@" / ">" / ","
    1814             :                                     // / ";">, or the next token is <":"> and
    1815             :                                     // is within a bracketed block:
    1816           0 :                                     const sal_Unicode * pLookAhead = pBodyPtr;
    1817           0 :                                     if (*pLookAhead == '"')
    1818             :                                     {
    1819             :                                         pLookAhead
    1820             :                                             = skipQuotedString(pLookAhead,
    1821           0 :                                                                pBodyEnd);
    1822           0 :                                         if (pLookAhead == pBodyPtr)
    1823           0 :                                             pLookAhead = pBodyEnd;
    1824             :                                     }
    1825             :                                     else
    1826           0 :                                         while (pLookAhead != pBodyEnd
    1827           0 :                                                && (isAtomChar(*pLookAhead)
    1828             :                                                    || !isUSASCII(
    1829           0 :                                                            *pLookAhead)))
    1830           0 :                                             ++pLookAhead;
    1831           0 :                                     while (pLookAhead != pBodyEnd)
    1832           0 :                                         switch (*pLookAhead)
    1833             :                                         {
    1834             :                                             case '\t':
    1835             :                                             case ' ':
    1836           0 :                                                 ++pLookAhead;
    1837           0 :                                                 break;
    1838             : 
    1839             :                                             case '(':
    1840             :                                             {
    1841             :                                                 const sal_Unicode * pPast
    1842             :                                                     = skipComment(pLookAhead,
    1843           0 :                                                                   pBodyEnd);
    1844             :                                                 pLookAhead
    1845             :                                                     = pPast == pLookAhead ?
    1846           0 :                                                           pBodyEnd : pPast;
    1847           0 :                                                 break;
    1848             :                                             }
    1849             : 
    1850             :                                             case ',':
    1851             :                                             case '.':
    1852             :                                             case ';':
    1853             :                                             case '>':
    1854             :                                             case '@':
    1855           0 :                                                 eEntity = ENTITY_NON_PHRASE;
    1856           0 :                                                 goto entity_determined;
    1857             : 
    1858             :                                             case ':':
    1859             :                                                 eEntity
    1860             :                                                     = eBrackets
    1861             :                                                          == BRACKETS_OUTSIDE ?
    1862             :                                                           ENTITY_PHRASE :
    1863           0 :                                                           ENTITY_NON_PHRASE;
    1864           0 :                                                 goto entity_determined;
    1865             : 
    1866             :                                             case '\x0D': // CR
    1867           0 :                                                 if (startsWithLineFolding(
    1868             :                                                         pLookAhead, pBodyEnd))
    1869             :                                                 {
    1870           0 :                                                     pLookAhead += 3;
    1871           0 :                                                     break;
    1872             :                                                 }
    1873             :                                             default:
    1874           0 :                                                 eEntity = ENTITY_PHRASE;
    1875           0 :                                                 goto entity_determined;
    1876             :                                         }
    1877           0 :                                     eEntity = ENTITY_NON_PHRASE;
    1878             :                                 entity_determined:
    1879           0 :                                     break;
    1880             :                                 }
    1881             : 
    1882             :                                 case HEADER_FIELD_TEXT:
    1883             :                                     OSL_ASSERT(false);
    1884           0 :                                     break;
    1885             :                             }
    1886             : 
    1887             :                             // In a 'non-phrase', a non-US-ASCII character
    1888             :                             // cannot be part of an <atom>, but instead the
    1889             :                             // whole entity is 'junk' rather than 'non-
    1890             :                             // phrase':
    1891           0 :                             if (eEntity == ENTITY_NON_PHRASE
    1892           0 :                                 && !isUSASCII(*pBodyPtr))
    1893           0 :                                 eEntity = ENTITY_JUNK;
    1894           0 :                             break;
    1895             :                     }
    1896             : 
    1897           0 :                     switch (eEntity)
    1898             :                     {
    1899             :                         case ENTITY_JUNK:
    1900             :                         {
    1901             :                             // Write a pending '<' if necessary:
    1902           0 :                             if (eBrackets == BRACKETS_OPENING)
    1903             :                             {
    1904           0 :                                 if (rSink.getColumn()
    1905             :                                             + (bInitialSpace ? 1 : 0)
    1906           0 :                                         >= rSink.getLineLengthLimit())
    1907           0 :                                     rSink << INetMIMEOutputSink::endl << ' ';
    1908           0 :                                 else if (bInitialSpace)
    1909           0 :                                     rSink << ' ';
    1910           0 :                                 rSink << '<';
    1911           0 :                                 bInitialSpace = false;
    1912           0 :                                 eBrackets = BRACKETS_INSIDE;
    1913             :                             }
    1914             : 
    1915             :                             // Calculate the length of in- and output:
    1916           0 :                             const sal_Unicode * pStart = pBodyPtr;
    1917           0 :                             sal_Size nLength = 0;
    1918           0 :                             bool bModify = false;
    1919           0 :                             bool bEnd = false;
    1920           0 :                             while (pBodyPtr != pBodyEnd && !bEnd)
    1921           0 :                                 switch (*pBodyPtr)
    1922             :                                 {
    1923             :                                     case '\x0D': // CR
    1924           0 :                                         if (startsWithLineFolding(pBodyPtr,
    1925             :                                                                   pBodyEnd))
    1926           0 :                                             bEnd = true;
    1927           0 :                                         else if (startsWithLineBreak(
    1928             :                                                      pBodyPtr, pBodyEnd))
    1929             :                                         {
    1930           0 :                                             nLength += 3;
    1931           0 :                                             bModify = true;
    1932           0 :                                             pBodyPtr += 2;
    1933             :                                         }
    1934             :                                         else
    1935             :                                         {
    1936           0 :                                             ++nLength;
    1937           0 :                                             ++pBodyPtr;
    1938             :                                         }
    1939           0 :                                         break;
    1940             : 
    1941             :                                     case '\t':
    1942             :                                     case ' ':
    1943           0 :                                         bEnd = true;
    1944           0 :                                         break;
    1945             : 
    1946             :                                     default:
    1947           0 :                                         if (isVisible(*pBodyPtr))
    1948           0 :                                             bEnd = true;
    1949           0 :                                         else if (isUSASCII(*pBodyPtr))
    1950             :                                         {
    1951           0 :                                             ++nLength;
    1952           0 :                                             ++pBodyPtr;
    1953             :                                         }
    1954             :                                         else
    1955             :                                         {
    1956             :                                             nLength += getUTF8OctetCount(
    1957           0 :                                                            *pBodyPtr++);
    1958           0 :                                             bModify = true;
    1959             :                                         }
    1960           0 :                                         break;
    1961             :                                 }
    1962             : 
    1963             :                             // Write the output:
    1964           0 :                             if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1965             :                                         + nLength
    1966           0 :                                     > rSink.getLineLengthLimit())
    1967           0 :                                 rSink << INetMIMEOutputSink::endl << ' ';
    1968           0 :                             else if (bInitialSpace)
    1969           0 :                                 rSink << ' ';
    1970           0 :                             bInitialSpace = false;
    1971           0 :                             if (bModify)
    1972           0 :                                 while (pStart != pBodyPtr)
    1973           0 :                                     if (startsWithLineBreak(pStart, pBodyPtr))
    1974             :                                     {
    1975           0 :                                         rSink << "\x0D\\\x0A"; // CR, '\', LF
    1976           0 :                                         pStart += 2;
    1977             :                                     }
    1978             :                                     else
    1979           0 :                                         writeUTF8(rSink, *pStart++);
    1980             :                             else
    1981           0 :                                 rSink.write(pStart, pBodyPtr);
    1982           0 :                             break;
    1983             :                         }
    1984             : 
    1985             :                         case ENTITY_NON_PHRASE:
    1986             :                         {
    1987             :                             // Calculate the length of in- and output:
    1988           0 :                             const sal_Unicode * pStart = pBodyPtr;
    1989           0 :                             sal_Size nLength = 0;
    1990           0 :                             bool bBracketedBlock = false;
    1991           0 :                             bool bSymbol = *pStart != '.' && *pStart != '@';
    1992           0 :                             bool bModify = false;
    1993           0 :                             bool bEnd = false;
    1994           0 :                             while (pBodyPtr != pBodyEnd && !bEnd)
    1995           0 :                                 switch (*pBodyPtr)
    1996             :                                 {
    1997             :                                     case '\t':
    1998             :                                     case ' ':
    1999             :                                     case '\x0D': // CR
    2000             :                                     {
    2001             :                                         const sal_Unicode * pLookAhead
    2002             :                                             = skipLinearWhiteSpace(pBodyPtr,
    2003           0 :                                                                    pBodyEnd);
    2004           0 :                                         if (pLookAhead < pBodyEnd
    2005             :                                             && (bSymbol ?
    2006           0 :                                                     isAtomChar(*pLookAhead)
    2007             :                                                     || *pLookAhead == '"'
    2008             :                                                     || *pLookAhead == '[' :
    2009             :                                                     *pLookAhead == '.'
    2010             :                                                     || *pLookAhead == '@'
    2011             :                                                     || (*pLookAhead == '>'
    2012             :                                                        && eType
    2013             :                                                     >= HEADER_FIELD_MESSAGE_ID
    2014             :                                                        && eBrackets
    2015             :                                                          == BRACKETS_OPENING)))
    2016             :                                         {
    2017           0 :                                             bModify = true;
    2018           0 :                                             pBodyPtr = pLookAhead;
    2019             :                                         }
    2020             :                                         else
    2021           0 :                                             bEnd = true;
    2022           0 :                                         break;
    2023             :                                     }
    2024             : 
    2025             :                                     case '"':
    2026           0 :                                         if (bSymbol)
    2027             :                                         {
    2028             :                                             pBodyPtr
    2029             :                                                 = scanQuotedBlock(pBodyPtr,
    2030             :                                                                   pBodyEnd,
    2031             :                                                                   '"', '"',
    2032             :                                                                   nLength,
    2033           0 :                                                                   bModify);
    2034           0 :                                             bSymbol = false;
    2035             :                                         }
    2036             :                                         else
    2037           0 :                                             bEnd = true;
    2038           0 :                                         break;
    2039             : 
    2040             :                                     case '[':
    2041           0 :                                         if (bSymbol)
    2042             :                                         {
    2043             :                                             pBodyPtr
    2044             :                                                 = scanQuotedBlock(pBodyPtr,
    2045             :                                                                   pBodyEnd,
    2046             :                                                                   '[', ']',
    2047             :                                                                   nLength,
    2048           0 :                                                                   bModify);
    2049           0 :                                             bSymbol = false;
    2050             :                                         }
    2051             :                                         else
    2052           0 :                                             bEnd = true;
    2053           0 :                                         break;
    2054             : 
    2055             :                                     case '.':
    2056             :                                     case '@':
    2057           0 :                                         if (bSymbol)
    2058           0 :                                             bEnd = true;
    2059             :                                         else
    2060             :                                         {
    2061           0 :                                             ++nLength;
    2062           0 :                                             bSymbol = true;
    2063           0 :                                             ++pBodyPtr;
    2064             :                                         }
    2065           0 :                                         break;
    2066             : 
    2067             :                                     case '>':
    2068           0 :                                         if (eBrackets == BRACKETS_OPENING
    2069             :                                             && eType
    2070             :                                                    >= HEADER_FIELD_MESSAGE_ID)
    2071             :                                         {
    2072           0 :                                             ++nLength;
    2073           0 :                                             bBracketedBlock = true;
    2074           0 :                                             ++pBodyPtr;
    2075             :                                         }
    2076           0 :                                         bEnd = true;
    2077           0 :                                         break;
    2078             : 
    2079             :                                     default:
    2080           0 :                                         if (isAtomChar(*pBodyPtr) && bSymbol)
    2081             :                                         {
    2082           0 :                                             while (pBodyPtr != pBodyEnd
    2083           0 :                                                    && isAtomChar(*pBodyPtr))
    2084             :                                             {
    2085           0 :                                                 ++nLength;
    2086           0 :                                                 ++pBodyPtr;
    2087             :                                             }
    2088           0 :                                             bSymbol = false;
    2089             :                                         }
    2090             :                                         else
    2091             :                                         {
    2092           0 :                                             if (!isUSASCII(*pBodyPtr))
    2093           0 :                                                 bModify = true;
    2094           0 :                                             bEnd = true;
    2095             :                                         }
    2096           0 :                                         break;
    2097             :                                 }
    2098             : 
    2099             :                             // Write a pending '<' if necessary:
    2100           0 :                             if (eBrackets == BRACKETS_OPENING
    2101           0 :                                 && !bBracketedBlock)
    2102             :                             {
    2103           0 :                                 if (rSink.getColumn()
    2104             :                                             + (bInitialSpace ? 1 : 0)
    2105           0 :                                         >= rSink.getLineLengthLimit())
    2106           0 :                                     rSink << INetMIMEOutputSink::endl << ' ';
    2107           0 :                                 else if (bInitialSpace)
    2108           0 :                                     rSink << ' ';
    2109           0 :                                 rSink << '<';
    2110           0 :                                 bInitialSpace = false;
    2111           0 :                                 eBrackets = BRACKETS_INSIDE;
    2112             :                             }
    2113             : 
    2114             :                             // Write the output:
    2115           0 :                             if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    2116             :                                         + nLength
    2117           0 :                                     > rSink.getLineLengthLimit())
    2118           0 :                                 rSink << INetMIMEOutputSink::endl << ' ';
    2119           0 :                             else if (bInitialSpace)
    2120           0 :                                 rSink << ' ';
    2121           0 :                             bInitialSpace = false;
    2122           0 :                             if (bBracketedBlock)
    2123             :                             {
    2124           0 :                                 rSink << '<';
    2125           0 :                                 eBrackets = BRACKETS_OUTSIDE;
    2126             :                             }
    2127           0 :                             if (bModify)
    2128             :                             {
    2129             :                                 enum Mode { MODE_PLAIN, MODE_QUOTED_STRING,
    2130             :                                             MODE_DOMAIN_LITERAL };
    2131           0 :                                 Mode eMode = MODE_PLAIN;
    2132           0 :                                 while (pStart != pBodyPtr)
    2133           0 :                                     switch (*pStart)
    2134             :                                     {
    2135             :                                         case '\x0D': // CR
    2136           0 :                                             if (startsWithLineFolding(
    2137             :                                                     pStart, pBodyPtr))
    2138             :                                             {
    2139           0 :                                                 if (eMode != MODE_PLAIN)
    2140             :                                                     rSink << sal_Char(
    2141           0 :                                                                  pStart[2]);
    2142           0 :                                                 pStart += 3;
    2143             :                                             }
    2144           0 :                                             else if (startsWithLineBreak(
    2145             :                                                          pStart, pBodyPtr))
    2146             :                                             {
    2147           0 :                                                 rSink << "\x0D\\\x0A";
    2148             :                                                     // CR, '\', LF
    2149           0 :                                                 pStart += 2;
    2150             :                                             }
    2151             :                                             else
    2152             :                                             {
    2153           0 :                                                 rSink << '\x0D'; // CR
    2154           0 :                                                 ++pStart;
    2155             :                                             }
    2156           0 :                                             break;
    2157             : 
    2158             :                                         case '\t':
    2159             :                                         case ' ':
    2160           0 :                                             if (eMode != MODE_PLAIN)
    2161           0 :                                                 rSink << sal_Char(*pStart);
    2162           0 :                                             ++pStart;
    2163           0 :                                             break;
    2164             : 
    2165             :                                         case '"':
    2166           0 :                                             if (eMode == MODE_PLAIN)
    2167           0 :                                                 eMode = MODE_QUOTED_STRING;
    2168           0 :                                             else if (eMode
    2169             :                                                         == MODE_QUOTED_STRING)
    2170           0 :                                                 eMode = MODE_PLAIN;
    2171           0 :                                             rSink << '"';
    2172           0 :                                             ++pStart;
    2173           0 :                                             break;
    2174             : 
    2175             :                                         case '[':
    2176           0 :                                             if (eMode == MODE_PLAIN)
    2177           0 :                                                 eMode = MODE_DOMAIN_LITERAL;
    2178           0 :                                             rSink << '[';
    2179           0 :                                             ++pStart;
    2180           0 :                                             break;
    2181             : 
    2182             :                                         case ']':
    2183           0 :                                             if (eMode == MODE_DOMAIN_LITERAL)
    2184           0 :                                                 eMode = MODE_PLAIN;
    2185           0 :                                             rSink << ']';
    2186           0 :                                             ++pStart;
    2187           0 :                                             break;
    2188             : 
    2189             :                                         case '\\':
    2190           0 :                                             rSink << '\\';
    2191           0 :                                             if (++pStart < pBodyPtr)
    2192           0 :                                                 writeUTF8(rSink, *pStart++);
    2193           0 :                                             break;
    2194             : 
    2195             :                                         default:
    2196           0 :                                             writeUTF8(rSink, *pStart++);
    2197           0 :                                             break;
    2198             :                                     }
    2199             :                             }
    2200             :                             else
    2201           0 :                                 rSink.write(pStart, pBodyPtr);
    2202             :                             break;
    2203             :                         }
    2204             : 
    2205             :                         case ENTITY_PHRASE:
    2206             :                         {
    2207             :                             // Write a pending '<' if necessary:
    2208           0 :                             if (eBrackets == BRACKETS_OPENING)
    2209             :                             {
    2210           0 :                                 if (rSink.getColumn()
    2211             :                                             + (bInitialSpace ? 1 : 0)
    2212           0 :                                         >= rSink.getLineLengthLimit())
    2213           0 :                                     rSink << INetMIMEOutputSink::endl << ' ';
    2214           0 :                                 else if (bInitialSpace)
    2215           0 :                                     rSink << ' ';
    2216           0 :                                 rSink << '<';
    2217           0 :                                 bInitialSpace = false;
    2218           0 :                                 eBrackets = BRACKETS_INSIDE;
    2219             :                             }
    2220             : 
    2221             :                             // Calculate the length of in- and output:
    2222           0 :                             const sal_Unicode * pStart = pBodyPtr;
    2223           0 :                             bool bQuotedString = false;
    2224           0 :                             bool bEnd = false;
    2225           0 :                             while (pBodyPtr != pBodyEnd && !bEnd)
    2226           0 :                                 switch (*pBodyPtr)
    2227             :                                 {
    2228             :                                     case '\t':
    2229             :                                     case ' ':
    2230             :                                     case '\x0D': // CR
    2231           0 :                                         if (bQuotedString)
    2232           0 :                                             ++pBodyPtr;
    2233             :                                         else
    2234             :                                         {
    2235             :                                             const sal_Unicode * pLookAhead
    2236             :                                                 = skipLinearWhiteSpace(
    2237           0 :                                                       pBodyPtr, pBodyEnd);
    2238           0 :                                             if (pLookAhead != pBodyEnd
    2239           0 :                                                 && (isAtomChar(*pLookAhead)
    2240           0 :                                                     || !isUSASCII(*pLookAhead)
    2241             :                                                     || *pLookAhead == '"'))
    2242           0 :                                                 pBodyPtr = pLookAhead;
    2243             :                                             else
    2244           0 :                                                 bEnd = true;
    2245             :                                         }
    2246           0 :                                         break;
    2247             : 
    2248             :                                     case '"':
    2249           0 :                                         bQuotedString = !bQuotedString;
    2250           0 :                                         ++pBodyPtr;
    2251           0 :                                         break;
    2252             : 
    2253             :                                     case '\\':
    2254           0 :                                         if (bQuotedString)
    2255             :                                         {
    2256           0 :                                             if (++pBodyPtr != pBodyEnd)
    2257           0 :                                                 ++pBodyPtr;
    2258             :                                         }
    2259             :                                         else
    2260           0 :                                             bEnd = true;
    2261           0 :                                         break;
    2262             : 
    2263             :                                     default:
    2264           0 :                                         if (bQuotedString
    2265           0 :                                             || isAtomChar(*pBodyPtr)
    2266           0 :                                             || !isUSASCII(*pBodyPtr))
    2267           0 :                                             ++pBodyPtr;
    2268             :                                         else
    2269           0 :                                             bEnd = true;
    2270           0 :                                         break;
    2271             :                                 }
    2272             : 
    2273             :                             // Write the phrase, introducing encoded-words
    2274             :                             // where necessary:
    2275             :                             INetMIMEEncodedWordOutputSink
    2276             :                                 aOutput(
    2277             :                                     rSink,
    2278             :                                 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,
    2279             :                                     bInitialSpace ?
    2280             :                                  INetMIMEEncodedWordOutputSink::SPACE_ALWAYS :
    2281             :                                  INetMIMEEncodedWordOutputSink::SPACE_ENCODED,
    2282           0 :                                ePreferredEncoding);
    2283           0 :                             while (pStart != pBodyPtr)
    2284           0 :                                 switch (*pStart)
    2285             :                                 {
    2286             :                                     case '"':
    2287           0 :                                         ++pStart;
    2288           0 :                                         break;
    2289             : 
    2290             :                                     case '\\':
    2291           0 :                                         if (++pStart != pBodyPtr)
    2292           0 :                                             aOutput << *pStart++;
    2293           0 :                                         break;
    2294             : 
    2295             :                                     case '\x0D': // CR
    2296           0 :                                         pStart += 2;
    2297           0 :                                         aOutput << *pStart++;
    2298           0 :                                         break;
    2299             : 
    2300             :                                     default:
    2301           0 :                                         aOutput << *pStart++;
    2302           0 :                                         break;
    2303             :                                 }
    2304           0 :                             bInitialSpace = aOutput.flush();
    2305           0 :                             break;
    2306             :                         }
    2307             :                     }
    2308           0 :                     break;
    2309             :                 }
    2310             :             }
    2311             :     }
    2312           0 : }
    2313             : 
    2314             : // static
    2315           0 : bool INetMIME::translateUTF8Char(const sal_Char *& rBegin,
    2316             :                                  const sal_Char * pEnd,
    2317             :                                  rtl_TextEncoding eEncoding,
    2318             :                                  sal_uInt32 & rCharacter)
    2319             : {
    2320           0 :     if (rBegin == pEnd || static_cast< unsigned char >(*rBegin) < 0x80
    2321             :         || static_cast< unsigned char >(*rBegin) >= 0xFE)
    2322           0 :         return false;
    2323             : 
    2324             :     int nCount;
    2325             :     sal_uInt32 nMin;
    2326             :     sal_uInt32 nUCS4;
    2327           0 :     const sal_Char * p = rBegin;
    2328           0 :     if (static_cast< unsigned char >(*p) < 0xE0)
    2329             :     {
    2330           0 :         nCount = 1;
    2331           0 :         nMin = 0x80;
    2332           0 :         nUCS4 = static_cast< unsigned char >(*p) & 0x1F;
    2333             :     }
    2334           0 :     else if (static_cast< unsigned char >(*p) < 0xF0)
    2335             :     {
    2336           0 :         nCount = 2;
    2337           0 :         nMin = 0x800;
    2338           0 :         nUCS4 = static_cast< unsigned char >(*p) & 0xF;
    2339             :     }
    2340           0 :     else if (static_cast< unsigned char >(*p) < 0xF8)
    2341             :     {
    2342           0 :         nCount = 3;
    2343           0 :         nMin = 0x10000;
    2344           0 :         nUCS4 = static_cast< unsigned char >(*p) & 7;
    2345             :     }
    2346           0 :     else if (static_cast< unsigned char >(*p) < 0xFC)
    2347             :     {
    2348           0 :         nCount = 4;
    2349           0 :         nMin = 0x200000;
    2350           0 :         nUCS4 = static_cast< unsigned char >(*p) & 3;
    2351             :     }
    2352             :     else
    2353             :     {
    2354           0 :         nCount = 5;
    2355           0 :         nMin = 0x4000000;
    2356           0 :         nUCS4 = static_cast< unsigned char >(*p) & 1;
    2357             :     }
    2358           0 :     ++p;
    2359             : 
    2360           0 :     for (; nCount-- > 0; ++p)
    2361           0 :         if ((static_cast< unsigned char >(*p) & 0xC0) == 0x80)
    2362           0 :             nUCS4 = (nUCS4 << 6) | (static_cast< unsigned char >(*p) & 0x3F);
    2363             :         else
    2364           0 :             return false;
    2365             : 
    2366           0 :     if (nUCS4 < nMin || nUCS4 > 0x10FFFF)
    2367           0 :         return false;
    2368             : 
    2369           0 :     if (eEncoding >= RTL_TEXTENCODING_UCS4)
    2370           0 :         rCharacter = nUCS4;
    2371             :     else
    2372             :     {
    2373             :         sal_Unicode aUTF16[2];
    2374           0 :         const sal_Unicode * pUTF16End = putUTF32Character(aUTF16, nUCS4);
    2375             :         sal_Size nSize;
    2376             :         sal_Char * pBuffer = convertFromUnicode(aUTF16, pUTF16End, eEncoding,
    2377           0 :                                                 nSize);
    2378           0 :         if (!pBuffer)
    2379           0 :             return false;
    2380             :         DBG_ASSERT(nSize == 1,
    2381             :                    "INetMIME::translateUTF8Char(): Bad conversion");
    2382           0 :         rCharacter = *pBuffer;
    2383           0 :         delete[] pBuffer;
    2384             :     }
    2385           0 :     rBegin = p;
    2386           0 :     return true;
    2387             : }
    2388             : 
    2389             : // static
    2390           3 : rtl::OUString INetMIME::decodeHeaderFieldBody(HeaderFieldType eType,
    2391             :                                           const rtl::OString& rBody)
    2392             : {
    2393             :     // Due to a bug in INetCoreRFC822MessageStream::ConvertTo7Bit(), old
    2394             :     // versions of StarOffice send mails with header fields where encoded
    2395             :     // words can be preceded by '=', ',', '.', '"', or '(', and followed by
    2396             :     // '=', ',', '.', '"', ')', without any required white space in between.
    2397             :     // And there appear to exist some broken mailers that only encode single
    2398             :     // letters within words, like "Appel
    2399             :     // =?iso-8859-1?Q?=E0?=t=?iso-8859-1?Q?=E9?=moin", so it seems best to
    2400             :     // detect encoded words even when not propperly surrounded by white space.
    2401             :     //
    2402             :     // Non US-ASCII characters in rBody are treated as ISO-8859-1.
    2403             :     //
    2404             :     // encoded-word = "=?"
    2405             :     //     1*(%x21 / %x23-27 / %x2A-2B / %x2D / %30-39 / %x41-5A / %x5E-7E)
    2406             :     //     ["*" 1*8ALPHA *("-" 1*8ALPHA)] "?"
    2407             :     //     ("B?" *(4base64) (4base64 / 3base64 "=" / 2base64 "==")
    2408             :     //      / "Q?" 1*(%x21-3C / %x3E / %x40-7E / "=" 2HEXDIG))
    2409             :     //     "?="
    2410             :     //
    2411             :     // base64 = ALPHA / DIGIT / "+" / "/"
    2412             : 
    2413           3 :     const sal_Char * pBegin = rBody.getStr();
    2414           3 :     const sal_Char * pEnd = pBegin + rBody.getLength();
    2415             : 
    2416           3 :     UniString sDecoded;
    2417           3 :     const sal_Char * pCopyBegin = pBegin;
    2418             : 
    2419             :     /* bool bStartEncodedWord = true; */
    2420           3 :     const sal_Char * pWSPBegin = pBegin;
    2421           3 :     bool bQuotedEncodedText = false;
    2422           3 :     sal_uInt32 nCommentLevel = 0;
    2423             : 
    2424           9 :     for (const sal_Char * p = pBegin; p != pEnd;)
    2425             :     {
    2426           3 :         rtl::OUString sEncodedText;
    2427           3 :         if (p != pEnd && *p == '=' /* && bStartEncodedWord */)
    2428             :         {
    2429           3 :             const sal_Char * q = p + 1;
    2430           3 :             bool bEncodedWord = q != pEnd && *q++ == '?';
    2431             : 
    2432           3 :             rtl_TextEncoding eCharsetEncoding = RTL_TEXTENCODING_DONTKNOW;
    2433           3 :             if (bEncodedWord)
    2434             :             {
    2435           3 :                 const sal_Char * pCharsetBegin = q;
    2436           3 :                 const sal_Char * pLanguageBegin = 0;
    2437           3 :                 int nAlphaCount = 0;
    2438          39 :                 for (bool bDone = false; !bDone;)
    2439          33 :                     if (q == pEnd)
    2440             :                     {
    2441           0 :                         bEncodedWord = false;
    2442           0 :                         bDone = true;
    2443             :                     }
    2444             :                     else
    2445             :                     {
    2446          33 :                         sal_Char cChar = *q++;
    2447          33 :                         switch (cChar)
    2448             :                         {
    2449             :                             case '*':
    2450           0 :                                 pLanguageBegin = q - 1;
    2451           0 :                                 nAlphaCount = 0;
    2452           0 :                                 break;
    2453             : 
    2454             :                             case '-':
    2455           6 :                                 if (pLanguageBegin != 0)
    2456             :                                 {
    2457           0 :                                     if (nAlphaCount == 0)
    2458           0 :                                         pLanguageBegin = 0;
    2459             :                                     else
    2460           0 :                                         nAlphaCount = 0;
    2461             :                                 }
    2462           6 :                                 break;
    2463             : 
    2464             :                             case '?':
    2465           3 :                                 if (pCharsetBegin == q - 1)
    2466           0 :                                     bEncodedWord = false;
    2467             :                                 else
    2468             :                                 {
    2469             :                                     eCharsetEncoding
    2470             :                                         = getCharsetEncoding(
    2471             :                                               pCharsetBegin,
    2472             :                                               pLanguageBegin == 0
    2473             :                                               || nAlphaCount == 0 ?
    2474           3 :                                                   q - 1 : pLanguageBegin);
    2475             :                                     bEncodedWord = isMIMECharsetEncoding(
    2476           3 :                                                        eCharsetEncoding);
    2477             :                                     eCharsetEncoding
    2478           3 :                                         = translateFromMIME(eCharsetEncoding);
    2479             :                                 }
    2480           3 :                                 bDone = true;
    2481           3 :                                 break;
    2482             : 
    2483             :                             default:
    2484          24 :                                 if (pLanguageBegin != 0
    2485           0 :                                     && (!isAlpha(cChar) || ++nAlphaCount > 8))
    2486           0 :                                     pLanguageBegin = 0;
    2487          24 :                                 break;
    2488             :                         }
    2489             :                     }
    2490             :             }
    2491             : 
    2492           3 :             bool bEncodingB = false;
    2493           3 :             if (bEncodedWord)
    2494             :             {
    2495           3 :                 if (q == pEnd)
    2496           0 :                     bEncodedWord = false;
    2497             :                 else
    2498             :                 {
    2499           3 :                     switch (*q++)
    2500             :                     {
    2501             :                         case 'B':
    2502             :                         case 'b':
    2503           3 :                             bEncodingB = true;
    2504           3 :                             break;
    2505             : 
    2506             :                         case 'Q':
    2507             :                         case 'q':
    2508           0 :                             bEncodingB = false;
    2509           0 :                             break;
    2510             : 
    2511             :                         default:
    2512           0 :                             bEncodedWord = false;
    2513           0 :                             break;
    2514             :                     }
    2515             :                 }
    2516             :             }
    2517             : 
    2518           3 :             bEncodedWord = bEncodedWord && q != pEnd && *q++ == '?';
    2519             : 
    2520           3 :             rtl::OStringBuffer sText;
    2521           3 :             if (bEncodedWord)
    2522             :             {
    2523           3 :                 if (bEncodingB)
    2524             :                 {
    2525           9 :                     for (bool bDone = false; !bDone;)
    2526             :                     {
    2527           3 :                         if (pEnd - q < 4)
    2528             :                         {
    2529           0 :                             bEncodedWord = false;
    2530           0 :                             bDone = true;
    2531             :                         }
    2532             :                         else
    2533             :                         {
    2534           3 :                             bool bFinal = false;
    2535           3 :                             int nCount = 3;
    2536           3 :                             sal_uInt32 nValue = 0;
    2537          15 :                             for (int nShift = 18; nShift >= 0; nShift -= 6)
    2538             :                             {
    2539          12 :                                 int nWeight = getBase64Weight(*q++);
    2540          12 :                                 if (nWeight == -2)
    2541             :                                 {
    2542           0 :                                     bEncodedWord = false;
    2543           0 :                                     bDone = true;
    2544           0 :                                     break;
    2545             :                                 }
    2546          12 :                                 if (nWeight == -1)
    2547             :                                 {
    2548           3 :                                     if (!bFinal)
    2549             :                                     {
    2550           2 :                                         if (nShift >= 12)
    2551             :                                         {
    2552           0 :                                             bEncodedWord = false;
    2553           0 :                                             bDone = true;
    2554           0 :                                             break;
    2555             :                                         }
    2556           2 :                                         bFinal = true;
    2557           2 :                                         nCount = nShift == 6 ? 1 : 2;
    2558             :                                     }
    2559             :                                 }
    2560             :                                 else
    2561           9 :                                     nValue |= nWeight << nShift;
    2562             :                             }
    2563           3 :                             if (bEncodedWord)
    2564             :                             {
    2565           9 :                                 for (int nShift = 16; nCount-- > 0; nShift -= 8)
    2566           6 :                                     sText.append(sal_Char(nValue >> nShift & 0xFF));
    2567           3 :                                 if (*q == '?')
    2568             :                                 {
    2569           3 :                                     ++q;
    2570           3 :                                     bDone = true;
    2571             :                                 }
    2572           3 :                                 if (bFinal && !bDone)
    2573             :                                 {
    2574           0 :                                     bEncodedWord = false;
    2575           0 :                                     bDone = true;
    2576             :                                 }
    2577             :                             }
    2578             :                         }
    2579             :                     }
    2580             :                 }
    2581             :                 else
    2582             :                 {
    2583           0 :                     const sal_Char * pEncodedTextBegin = q;
    2584           0 :                     const sal_Char * pEncodedTextCopyBegin = q;
    2585           0 :                     for (bool bDone = false; !bDone;)
    2586           0 :                         if (q == pEnd)
    2587             :                         {
    2588           0 :                             bEncodedWord = false;
    2589           0 :                             bDone = true;
    2590             :                         }
    2591             :                         else
    2592             :                         {
    2593           0 :                             sal_uInt32 nChar = *q++;
    2594           0 :                             switch (nChar)
    2595             :                             {
    2596             :                                 case '=':
    2597             :                                 {
    2598           0 :                                     if (pEnd - q < 2)
    2599             :                                     {
    2600           0 :                                         bEncodedWord = false;
    2601           0 :                                         bDone = true;
    2602           0 :                                         break;
    2603             :                                     }
    2604           0 :                                     int nDigit1 = getHexWeight(q[0]);
    2605           0 :                                     int nDigit2 = getHexWeight(q[1]);
    2606           0 :                                     if (nDigit1 < 0 || nDigit2 < 0)
    2607             :                                     {
    2608           0 :                                         bEncodedWord = false;
    2609           0 :                                         bDone = true;
    2610           0 :                                         break;
    2611             :                                     }
    2612             :                                     sText.append(rBody.copy(
    2613             :                                         (pEncodedTextCopyBegin - pBegin),
    2614           0 :                                         (q - 1 - pEncodedTextCopyBegin)));
    2615           0 :                                     sText.append(sal_Char(nDigit1 << 4 | nDigit2));
    2616           0 :                                     q += 2;
    2617           0 :                                     pEncodedTextCopyBegin = q;
    2618           0 :                                     break;
    2619             :                                 }
    2620             : 
    2621             :                                 case '?':
    2622           0 :                                     if (q - pEncodedTextBegin > 1)
    2623             :                                         sText.append(rBody.copy(
    2624             :                                             (pEncodedTextCopyBegin - pBegin),
    2625           0 :                                             (q - 1 - pEncodedTextCopyBegin)));
    2626             :                                     else
    2627           0 :                                         bEncodedWord = false;
    2628           0 :                                     bDone = true;
    2629           0 :                                     break;
    2630             : 
    2631             :                                 case '_':
    2632             :                                     sText.append(rBody.copy(
    2633             :                                         (pEncodedTextCopyBegin - pBegin),
    2634           0 :                                         (q - 1 - pEncodedTextCopyBegin)));
    2635           0 :                                     sText.append(' ');
    2636           0 :                                     pEncodedTextCopyBegin = q;
    2637           0 :                                     break;
    2638             : 
    2639             :                                 default:
    2640           0 :                                     if (!isVisible(nChar))
    2641             :                                     {
    2642           0 :                                         bEncodedWord = false;
    2643           0 :                                         bDone = true;
    2644             :                                     }
    2645           0 :                                     break;
    2646             :                             }
    2647             :                         }
    2648             :                 }
    2649             :             }
    2650             : 
    2651           3 :             bEncodedWord = bEncodedWord && q != pEnd && *q++ == '=';
    2652             : 
    2653           3 :             sal_Unicode * pUnicodeBuffer = 0;
    2654           3 :             sal_Size nUnicodeSize = 0;
    2655           3 :             if (bEncodedWord)
    2656             :             {
    2657             :                 pUnicodeBuffer
    2658             :                     = convertToUnicode(sText.getStr(),
    2659           3 :                                        sText.getStr() + sText.getLength(),
    2660           6 :                                        eCharsetEncoding, nUnicodeSize);
    2661           3 :                 if (pUnicodeBuffer == 0)
    2662           0 :                     bEncodedWord = false;
    2663             :             }
    2664             : 
    2665           3 :             if (bEncodedWord)
    2666             :             {
    2667           3 :                 appendISO88591(sDecoded, pCopyBegin, pWSPBegin);
    2668           3 :                 if (eType == HEADER_FIELD_TEXT)
    2669             :                     sDecoded.Append(
    2670             :                         pUnicodeBuffer,
    2671           3 :                         static_cast< xub_StrLen >(nUnicodeSize));
    2672           0 :                 else if (nCommentLevel == 0)
    2673             :                 {
    2674           0 :                     sEncodedText = rtl::OUString(pUnicodeBuffer, nUnicodeSize);
    2675           0 :                     if (!bQuotedEncodedText)
    2676             :                     {
    2677           0 :                         const sal_Unicode * pTextPtr = pUnicodeBuffer;
    2678             :                         const sal_Unicode * pTextEnd = pTextPtr
    2679           0 :                                                            + nUnicodeSize;
    2680           0 :                         for (; pTextPtr != pTextEnd; ++pTextPtr)
    2681           0 :                             if (!isEncodedWordTokenChar(*pTextPtr))
    2682             :                             {
    2683           0 :                                 bQuotedEncodedText = true;
    2684           0 :                                 break;
    2685             :                             }
    2686             :                     }
    2687             :                 }
    2688             :                 else
    2689             :                 {
    2690           0 :                     const sal_Unicode * pTextPtr = pUnicodeBuffer;
    2691           0 :                     const sal_Unicode * pTextEnd = pTextPtr + nUnicodeSize;
    2692           0 :                     for (; pTextPtr != pTextEnd; ++pTextPtr)
    2693             :                     {
    2694           0 :                         switch (*pTextPtr)
    2695             :                         {
    2696             :                             case '(':
    2697             :                             case ')':
    2698             :                             case '\\':
    2699             :                             case '\x0D':
    2700             :                             case '=':
    2701           0 :                                 sDecoded += '\\';
    2702           0 :                                 break;
    2703             :                         }
    2704           0 :                         sDecoded += *pTextPtr;
    2705             :                     }
    2706             :                 }
    2707           3 :                 delete[] pUnicodeBuffer;
    2708           3 :                 p = q;
    2709           3 :                 pCopyBegin = p;
    2710             : 
    2711           3 :                 pWSPBegin = p;
    2712           6 :                 while (p != pEnd && isWhiteSpace(*p))
    2713           0 :                     ++p;
    2714             :                 /* bStartEncodedWord = p != pWSPBegin; */
    2715           3 :                 continue;
    2716           3 :             }
    2717             :         }
    2718             : 
    2719           0 :         if (!sEncodedText.isEmpty())
    2720             :         {
    2721           0 :             if (bQuotedEncodedText)
    2722             :             {
    2723           0 :                 sDecoded += '"';
    2724           0 :                 const sal_Unicode * pTextPtr = sEncodedText.getStr();
    2725           0 :                 const sal_Unicode * pTextEnd = pTextPtr + sEncodedText.getLength();
    2726           0 :                 for (;pTextPtr != pTextEnd; ++pTextPtr)
    2727             :                 {
    2728           0 :                     switch (*pTextPtr)
    2729             :                     {
    2730             :                         case '"':
    2731             :                         case '\\':
    2732             :                         case '\x0D':
    2733           0 :                             sDecoded += '\\';
    2734           0 :                             break;
    2735             :                     }
    2736           0 :                     sDecoded += *pTextPtr;
    2737             :                 }
    2738           0 :                 sDecoded += '"';
    2739             :             }
    2740             :             else
    2741           0 :                 sDecoded += sEncodedText;
    2742           0 :             bQuotedEncodedText = false;
    2743             :         }
    2744             : 
    2745           0 :         if (p == pEnd)
    2746             :             break;
    2747             : 
    2748           0 :         switch (*p++)
    2749             :         {
    2750             :             case '"':
    2751           0 :                 if (eType != HEADER_FIELD_TEXT && nCommentLevel == 0)
    2752             :                 {
    2753             :                     const sal_Char * pQuotedStringEnd
    2754           0 :                         = skipQuotedString(p - 1, pEnd);
    2755           0 :                     p = pQuotedStringEnd == p - 1 ? pEnd : pQuotedStringEnd;
    2756             :                 }
    2757             :                 /* bStartEncodedWord = true; */
    2758           0 :                 break;
    2759             : 
    2760             :             case '(':
    2761           0 :                 if (eType != HEADER_FIELD_TEXT)
    2762           0 :                     ++nCommentLevel;
    2763             :                 /* bStartEncodedWord = true; */
    2764           0 :                 break;
    2765             : 
    2766             :             case ')':
    2767           0 :                 if (nCommentLevel > 0)
    2768           0 :                     --nCommentLevel;
    2769             :                 /* bStartEncodedWord = false; */
    2770           0 :                 break;
    2771             : 
    2772             :             default:
    2773             :             {
    2774           0 :                 const sal_Char * pUTF8Begin = p - 1;
    2775           0 :                 const sal_Char * pUTF8End = pUTF8Begin;
    2776           0 :                 sal_uInt32 nCharacter = 0;
    2777           0 :                 if (translateUTF8Char(pUTF8End, pEnd, RTL_TEXTENCODING_UCS4,
    2778             :                                       nCharacter))
    2779             :                 {
    2780           0 :                     appendISO88591(sDecoded, pCopyBegin, p - 1);
    2781             :                     sal_Unicode aUTF16Buf[2];
    2782             :                     xub_StrLen nUTF16Len = static_cast< xub_StrLen >(
    2783           0 :                         putUTF32Character(aUTF16Buf, nCharacter) - aUTF16Buf);
    2784           0 :                     sDecoded.Append(aUTF16Buf, nUTF16Len);
    2785           0 :                     p = pUTF8End;
    2786           0 :                     pCopyBegin = p;
    2787             :                 }
    2788             :                 /* bStartEncodedWord = false; */
    2789             :                 break;
    2790             :             }
    2791             :         }
    2792           0 :         pWSPBegin = p;
    2793           3 :     }
    2794             : 
    2795           3 :     appendISO88591(sDecoded, pCopyBegin, pEnd);
    2796           3 :     return sDecoded;
    2797             : }
    2798             : 
    2799             : //  INetMIMEOutputSink
    2800             : 
    2801             : // virtual
    2802           0 : sal_Size INetMIMEOutputSink::writeSequence(const sal_Char * pSequence)
    2803             : {
    2804           0 :     sal_Size nLength = rtl_str_getLength(pSequence);
    2805           0 :     writeSequence(pSequence, pSequence + nLength);
    2806           0 :     return nLength;
    2807             : }
    2808             : 
    2809             : // virtual
    2810           0 : void INetMIMEOutputSink::writeSequence(const sal_uInt32 * pBegin,
    2811             :                                        const sal_uInt32 * pEnd)
    2812             : {
    2813             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
    2814             :                "INetMIMEOutputSink::writeSequence(): Bad sequence");
    2815             : 
    2816           0 :     sal_Char * pBufferBegin = new sal_Char[pEnd - pBegin];
    2817           0 :     sal_Char * pBufferEnd = pBufferBegin;
    2818           0 :     while (pBegin != pEnd)
    2819             :     {
    2820             :         DBG_ASSERT(*pBegin < 256,
    2821             :                    "INetMIMEOutputSink::writeSequence(): Bad octet");
    2822           0 :         *pBufferEnd++ = sal_Char(*pBegin++);
    2823             :     }
    2824           0 :     writeSequence(pBufferBegin, pBufferEnd);
    2825           0 :     delete[] pBufferBegin;
    2826           0 : }
    2827             : 
    2828             : // virtual
    2829           0 : void INetMIMEOutputSink::writeSequence(const sal_Unicode * pBegin,
    2830             :                                        const sal_Unicode * pEnd)
    2831             : {
    2832             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
    2833             :                "INetMIMEOutputSink::writeSequence(): Bad sequence");
    2834             : 
    2835           0 :     sal_Char * pBufferBegin = new sal_Char[pEnd - pBegin];
    2836           0 :     sal_Char * pBufferEnd = pBufferBegin;
    2837           0 :     while (pBegin != pEnd)
    2838             :     {
    2839             :         DBG_ASSERT(*pBegin < 256,
    2840             :                    "INetMIMEOutputSink::writeSequence(): Bad octet");
    2841           0 :         *pBufferEnd++ = sal_Char(*pBegin++);
    2842             :     }
    2843           0 :     writeSequence(pBufferBegin, pBufferEnd);
    2844           0 :     delete[] pBufferBegin;
    2845           0 : }
    2846             : 
    2847             : // virtual
    2848           0 : ErrCode INetMIMEOutputSink::getError() const
    2849             : {
    2850           0 :     return ERRCODE_NONE;
    2851             : }
    2852             : 
    2853           0 : void INetMIMEOutputSink::writeLineEnd()
    2854             : {
    2855             :     static const sal_Char aCRLF[2] = { 0x0D, 0x0A };
    2856           0 :     writeSequence(aCRLF, aCRLF + 2);
    2857           0 :     m_nColumn = 0;
    2858           0 : }
    2859             : 
    2860             : //  INetMIMEStringOutputSink
    2861             : 
    2862             : // virtual
    2863           0 : void INetMIMEStringOutputSink::writeSequence(const sal_Char * pBegin,
    2864             :                                              const sal_Char * pEnd)
    2865             : {
    2866             :     OSL_ENSURE(pBegin && pBegin <= pEnd,
    2867             :                "INetMIMEStringOutputSink::writeSequence(): Bad sequence");
    2868             : 
    2869           0 :     m_aBuffer.append(pBegin, pEnd - pBegin);
    2870           0 : }
    2871             : 
    2872             : // virtual
    2873           0 : ErrCode INetMIMEStringOutputSink::getError() const
    2874             : {
    2875           0 :     return ERRCODE_NONE;
    2876             : }
    2877             : 
    2878             : //  INetMIMEEncodedWordOutputSink
    2879             : 
    2880             : static const sal_Char aEscape[128]
    2881             :     = { INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x00
    2882             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x01
    2883             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x02
    2884             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x03
    2885             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x04
    2886             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x05
    2887             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x06
    2888             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x07
    2889             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x08
    2890             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x09
    2891             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x0A
    2892             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x0B
    2893             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x0C
    2894             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x0D
    2895             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x0E
    2896             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x0F
    2897             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x10
    2898             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x11
    2899             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x12
    2900             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x13
    2901             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x14
    2902             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x15
    2903             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x16
    2904             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x17
    2905             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x18
    2906             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x19
    2907             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x1A
    2908             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x1B
    2909             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x1C
    2910             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x1D
    2911             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x1E
    2912             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // 0x1F
    2913             :         0,   // ' '
    2914             :         0,   // '!'
    2915             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '"'
    2916             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '#'
    2917             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '$'
    2918             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '%'
    2919             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '&'
    2920             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '''
    2921             :         INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '('
    2922             :         INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // ')'
    2923             :         0,   // '*'
    2924             :         0,   // '+'
    2925             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // ','
    2926             :         0,   // '-'
    2927             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '.'
    2928             :         0,   // '/'
    2929             :         0,   // '0'
    2930             :         0,   // '1'
    2931             :         0,   // '2'
    2932             :         0,   // '3'
    2933             :         0,   // '4'
    2934             :         0,   // '5'
    2935             :         0,   // '6'
    2936             :         0,   // '7'
    2937             :         0,   // '8'
    2938             :         0,   // '9'
    2939             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // ':'
    2940             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // ';'
    2941             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '<'
    2942             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '='
    2943             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '>'
    2944             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '?'
    2945             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '@'
    2946             :         0,   // 'A'
    2947             :         0,   // 'B'
    2948             :         0,   // 'C'
    2949             :         0,   // 'D'
    2950             :         0,   // 'E'
    2951             :         0,   // 'F'
    2952             :         0,   // 'G'
    2953             :         0,   // 'H'
    2954             :         0,   // 'I'
    2955             :         0,   // 'J'
    2956             :         0,   // 'K'
    2957             :         0,   // 'L'
    2958             :         0,   // 'M'
    2959             :         0,   // 'N'
    2960             :         0,   // 'O'
    2961             :         0,   // 'P'
    2962             :         0,   // 'Q'
    2963             :         0,   // 'R'
    2964             :         0,   // 'S'
    2965             :         0,   // 'T'
    2966             :         0,   // 'U'
    2967             :         0,   // 'V'
    2968             :         0,   // 'W'
    2969             :         0,   // 'X'
    2970             :         0,   // 'Y'
    2971             :         0,   // 'Z'
    2972             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '['
    2973             :         INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '\'
    2974             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // ']'
    2975             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '^'
    2976             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '_'
    2977             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '`'
    2978             :         0,   // 'a'
    2979             :         0,   // 'b'
    2980             :         0,   // 'c'
    2981             :         0,   // 'd'
    2982             :         0,   // 'e'
    2983             :         0,   // 'f'
    2984             :         0,   // 'g'
    2985             :         0,   // 'h'
    2986             :         0,   // 'i'
    2987             :         0,   // 'j'
    2988             :         0,   // 'k'
    2989             :         0,   // 'l'
    2990             :         0,   // 'm'
    2991             :         0,   // 'n'
    2992             :         0,   // 'o'
    2993             :         0,   // 'p'
    2994             :         0,   // 'q'
    2995             :         0,   // 'r'
    2996             :         0,   // 's'
    2997             :         0,   // 't'
    2998             :         0,   // 'u'
    2999             :         0,   // 'v'
    3000             :         0,   // 'w'
    3001             :         0,   // 'x'
    3002             :         0,   // 'y'
    3003             :         0,   // 'z'
    3004             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '{'
    3005             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '|'
    3006             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '}'
    3007             :         INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,   // '~'
    3008             :         INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE }; // DEL
    3009             : 
    3010             : inline bool
    3011           0 : INetMIMEEncodedWordOutputSink::needsEncodedWordEscape(sal_uInt32 nChar) const
    3012             : {
    3013           0 :     return !INetMIME::isUSASCII(nChar) || aEscape[nChar] & m_eContext;
    3014             : }
    3015             : 
    3016           0 : void INetMIMEEncodedWordOutputSink::finish(bool bWriteTrailer)
    3017             : {
    3018           0 :     if (m_eInitialSpace == SPACE_ALWAYS && m_nExtraSpaces == 0)
    3019           0 :         m_nExtraSpaces = 1;
    3020             : 
    3021           0 :     if (m_eEncodedWordState == STATE_SECOND_EQUALS)
    3022             :     {
    3023             :         // If the text is already an encoded word, copy it verbatim:
    3024           0 :         sal_uInt32 nSize = m_pBufferEnd - m_pBuffer;
    3025           0 :         switch (m_ePrevCoding)
    3026             :         {
    3027             :             case CODING_QUOTED:
    3028           0 :                 m_rSink << '"';
    3029             :             case CODING_NONE:
    3030           0 :                 if (m_eInitialSpace == SPACE_ENCODED && m_nExtraSpaces == 0)
    3031           0 :                     m_nExtraSpaces = 1;
    3032           0 :                 for (; m_nExtraSpaces > 1; --m_nExtraSpaces)
    3033             :                 {
    3034           0 :                     if (m_rSink.getColumn() >= m_rSink.getLineLengthLimit())
    3035           0 :                         m_rSink << INetMIMEOutputSink::endl;
    3036           0 :                     m_rSink << ' ';
    3037             :                 }
    3038           0 :                 if (m_nExtraSpaces == 1)
    3039             :                 {
    3040           0 :                     if (m_rSink.getColumn() + nSize
    3041           0 :                             >= m_rSink.getLineLengthLimit())
    3042           0 :                         m_rSink << INetMIMEOutputSink::endl;
    3043           0 :                     m_rSink << ' ';
    3044             :                 }
    3045           0 :                 break;
    3046             : 
    3047             :             case CODING_ENCODED:
    3048             :             {
    3049             :                 const sal_Char * pCharsetName
    3050           0 :                  = INetMIME::getCharsetName(m_ePrevMIMEEncoding);
    3051           0 :                 while (m_nExtraSpaces-- > 0)
    3052             :                 {
    3053           0 :                     if (m_rSink.getColumn()
    3054           0 :                             > m_rSink.getLineLengthLimit() - 3)
    3055           0 :                         m_rSink << "?=" << INetMIMEOutputSink::endl << " =?"
    3056           0 :                                 << pCharsetName << "?Q?";
    3057           0 :                     m_rSink << '_';
    3058             :                 }
    3059           0 :                 m_rSink << "?=";
    3060             :             }
    3061             :             case CODING_ENCODED_TERMINATED:
    3062           0 :                 if (m_rSink.getColumn() + nSize
    3063           0 :                         > m_rSink.getLineLengthLimit() - 1)
    3064           0 :                     m_rSink << INetMIMEOutputSink::endl;
    3065           0 :                 m_rSink << ' ';
    3066           0 :                 break;
    3067             :         }
    3068           0 :         m_rSink.write(m_pBuffer, m_pBufferEnd);
    3069           0 :         m_eCoding = CODING_ENCODED_TERMINATED;
    3070             :     }
    3071             :     else
    3072             :     {
    3073             :         // If the text itself is too long to fit into a single line, make it
    3074             :         // into multiple encoded words:
    3075           0 :         switch (m_eCoding)
    3076             :         {
    3077             :             case CODING_NONE:
    3078           0 :                 if (m_nExtraSpaces == 0)
    3079             :                 {
    3080             :                     DBG_ASSERT(m_ePrevCoding == CODING_NONE
    3081             :                                || m_pBuffer == m_pBufferEnd,
    3082             :                                "INetMIMEEncodedWordOutputSink::finish():"
    3083             :                                    " Bad state");
    3084           0 :                     if (m_rSink.getColumn() + (m_pBufferEnd - m_pBuffer)
    3085           0 :                             > m_rSink.getLineLengthLimit())
    3086           0 :                         m_eCoding = CODING_ENCODED;
    3087             :                 }
    3088             :                 else
    3089             :                 {
    3090             :                     OSL_ASSERT(m_pBufferEnd >= m_pBuffer);
    3091           0 :                     if (static_cast< std::size_t >(m_pBufferEnd - m_pBuffer)
    3092           0 :                         > m_rSink.getLineLengthLimit() - 1)
    3093             :                     {
    3094           0 :                         m_eCoding = CODING_ENCODED;
    3095             :                     }
    3096             :                 }
    3097           0 :                 break;
    3098             : 
    3099             :             case CODING_QUOTED:
    3100           0 :                 if (m_nExtraSpaces == 0)
    3101             :                 {
    3102             :                     DBG_ASSERT(m_ePrevCoding == CODING_NONE,
    3103             :                                "INetMIMEEncodedWordOutputSink::finish():"
    3104             :                                    " Bad state");
    3105           0 :                     if (m_rSink.getColumn() + (m_pBufferEnd - m_pBuffer)
    3106             :                                 + m_nQuotedEscaped
    3107           0 :                             > m_rSink.getLineLengthLimit() - 2)
    3108           0 :                         m_eCoding = CODING_ENCODED;
    3109             :                 }
    3110           0 :                 else if ((m_pBufferEnd - m_pBuffer) + m_nQuotedEscaped
    3111           0 :                              > m_rSink.getLineLengthLimit() - 3)
    3112           0 :                     m_eCoding = CODING_ENCODED;
    3113           0 :                 break;
    3114             : 
    3115             :             default:
    3116           0 :                 break;
    3117             :         }
    3118             : 
    3119           0 :         switch (m_eCoding)
    3120             :         {
    3121             :             case CODING_NONE:
    3122           0 :                 switch (m_ePrevCoding)
    3123             :                 {
    3124             :                     case CODING_QUOTED:
    3125           0 :                         if (m_rSink.getColumn() + m_nExtraSpaces
    3126             :                                     + (m_pBufferEnd - m_pBuffer)
    3127           0 :                                 < m_rSink.getLineLengthLimit())
    3128           0 :                             m_eCoding = CODING_QUOTED;
    3129             :                         else
    3130           0 :                             m_rSink << '"';
    3131           0 :                         break;
    3132             : 
    3133             :                     case CODING_ENCODED:
    3134           0 :                         m_rSink << "?=";
    3135           0 :                         break;
    3136             : 
    3137             :                     default:
    3138           0 :                         break;
    3139             :                 }
    3140           0 :                 for (; m_nExtraSpaces > 1; --m_nExtraSpaces)
    3141             :                 {
    3142           0 :                     if (m_rSink.getColumn() >= m_rSink.getLineLengthLimit())
    3143           0 :                         m_rSink << INetMIMEOutputSink::endl;
    3144           0 :                     m_rSink << ' ';
    3145             :                 }
    3146           0 :                 if (m_nExtraSpaces == 1)
    3147             :                 {
    3148           0 :                     if (m_rSink.getColumn() + (m_pBufferEnd - m_pBuffer)
    3149           0 :                             >= m_rSink.getLineLengthLimit())
    3150           0 :                         m_rSink << INetMIMEOutputSink::endl;
    3151           0 :                     m_rSink << ' ';
    3152             :                 }
    3153           0 :                 m_rSink.write(m_pBuffer, m_pBufferEnd);
    3154           0 :                 if (m_eCoding == CODING_QUOTED && bWriteTrailer)
    3155             :                 {
    3156           0 :                     m_rSink << '"';
    3157           0 :                     m_eCoding = CODING_NONE;
    3158             :                 }
    3159           0 :                 break;
    3160             : 
    3161             :             case CODING_QUOTED:
    3162             :             {
    3163           0 :                 bool bInsertLeadingQuote = true;
    3164             :                 sal_uInt32 nSize = (m_pBufferEnd - m_pBuffer)
    3165           0 :                                        + m_nQuotedEscaped + 2;
    3166           0 :                 switch (m_ePrevCoding)
    3167             :                 {
    3168             :                     case CODING_QUOTED:
    3169           0 :                         if (m_rSink.getColumn() + m_nExtraSpaces + nSize - 1
    3170           0 :                                 < m_rSink.getLineLengthLimit())
    3171             :                         {
    3172           0 :                             bInsertLeadingQuote = false;
    3173           0 :                             --nSize;
    3174             :                         }
    3175             :                         else
    3176           0 :                             m_rSink << '"';
    3177           0 :                         break;
    3178             : 
    3179             :                     case CODING_ENCODED:
    3180           0 :                         m_rSink << "?=";
    3181           0 :                         break;
    3182             : 
    3183             :                     default:
    3184           0 :                         break;
    3185             :                 }
    3186           0 :                 for (; m_nExtraSpaces > 1; --m_nExtraSpaces)
    3187             :                 {
    3188           0 :                     if (m_rSink.getColumn() >= m_rSink.getLineLengthLimit())
    3189           0 :                         m_rSink << INetMIMEOutputSink::endl;
    3190           0 :                     m_rSink << ' ';
    3191             :                 }
    3192           0 :                 if (m_nExtraSpaces == 1)
    3193             :                 {
    3194           0 :                     if (m_rSink.getColumn() + nSize
    3195           0 :                             >= m_rSink.getLineLengthLimit())
    3196           0 :                         m_rSink << INetMIMEOutputSink::endl;
    3197           0 :                     m_rSink << ' ';
    3198             :                 }
    3199           0 :                 if (bInsertLeadingQuote)
    3200           0 :                     m_rSink << '"';
    3201           0 :                 for (const sal_Unicode * p = m_pBuffer; p != m_pBufferEnd;
    3202             :                      ++p)
    3203             :                 {
    3204           0 :                     if (INetMIME::needsQuotedStringEscape(*p))
    3205           0 :                         m_rSink << '\\';
    3206           0 :                     m_rSink << sal_Char(*p);
    3207             :                 }
    3208           0 :                 if (bWriteTrailer)
    3209             :                 {
    3210           0 :                     m_rSink << '"';
    3211           0 :                     m_eCoding = CODING_NONE;
    3212             :                 }
    3213           0 :                 break;
    3214             :             }
    3215             : 
    3216             :             case CODING_ENCODED:
    3217             :             {
    3218             :                 rtl_TextEncoding eCharsetEncoding
    3219             :                     = m_pEncodingList->
    3220           0 :                           getPreferredEncoding(RTL_TEXTENCODING_UTF8);
    3221             :                 rtl_TextEncoding eMIMEEncoding
    3222           0 :                     = INetMIME::translateToMIME(eCharsetEncoding);
    3223             : 
    3224             :                 // The non UTF-8 code will only work for stateless single byte
    3225             :                 // character encodings (see also below):
    3226           0 :                 sal_Char * pTargetBuffer = NULL;
    3227           0 :                 sal_Size nTargetSize = 0;
    3228             :                 sal_uInt32 nSize;
    3229           0 :                 if (eMIMEEncoding == RTL_TEXTENCODING_UTF8)
    3230             :                 {
    3231           0 :                     nSize = 0;
    3232           0 :                     for (sal_Unicode const * p = m_pBuffer;
    3233             :                          p != m_pBufferEnd;)
    3234             :                     {
    3235             :                         sal_uInt32 nUTF32
    3236           0 :                             = INetMIME::getUTF32Character(p, m_pBufferEnd);
    3237           0 :                         nSize += needsEncodedWordEscape(nUTF32) ?
    3238           0 :                                      3 * INetMIME::getUTF8OctetCount(nUTF32) :
    3239           0 :                                      1;
    3240             :                             // only US-ASCII characters (that are converted to
    3241             :                             // a single byte by UTF-8) need no encoded word
    3242             :                             // escapes...
    3243             :                     }
    3244             :                 }
    3245             :                 else
    3246             :                 {
    3247             :                     rtl_UnicodeToTextConverter hConverter
    3248           0 :                         = rtl_createUnicodeToTextConverter(eCharsetEncoding);
    3249             :                     rtl_UnicodeToTextContext hContext
    3250           0 :                         = rtl_createUnicodeToTextContext(hConverter);
    3251           0 :                     for (sal_Size nBufferSize = m_pBufferEnd - m_pBuffer;;
    3252             :                          nBufferSize += nBufferSize / 3 + 1)
    3253             :                     {
    3254           0 :                         pTargetBuffer = new sal_Char[nBufferSize];
    3255             :                         sal_uInt32 nInfo;
    3256             :                         sal_Size nSrcCvtBytes;
    3257             :                         nTargetSize
    3258             :                             = rtl_convertUnicodeToText(
    3259             :                                   hConverter, hContext, m_pBuffer,
    3260             :                                   m_pBufferEnd - m_pBuffer, pTargetBuffer,
    3261             :                                   nBufferSize,
    3262             :                                   RTL_UNICODETOTEXT_FLAGS_UNDEFINED_IGNORE
    3263             :                                      | RTL_UNICODETOTEXT_FLAGS_INVALID_IGNORE,
    3264           0 :                                   &nInfo, &nSrcCvtBytes);
    3265           0 :                         if (!(nInfo
    3266           0 :                                   & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL))
    3267             :                             break;
    3268           0 :                         delete[] pTargetBuffer;
    3269           0 :                         pTargetBuffer = NULL;
    3270           0 :                         rtl_resetUnicodeToTextContext(hConverter, hContext);
    3271             :                     }
    3272           0 :                     rtl_destroyUnicodeToTextContext(hConverter, hContext);
    3273           0 :                     rtl_destroyUnicodeToTextConverter(hConverter);
    3274             : 
    3275           0 :                     nSize = nTargetSize;
    3276           0 :                     for (sal_Size k = 0; k < nTargetSize; ++k)
    3277           0 :                         if (needsEncodedWordEscape(sal_uChar(
    3278           0 :                                                        pTargetBuffer[k])))
    3279           0 :                             nSize += 2;
    3280             :                 }
    3281             : 
    3282             :                 const sal_Char * pCharsetName
    3283           0 :                     = INetMIME::getCharsetName(eMIMEEncoding);
    3284           0 :                 sal_uInt32 nWrapperSize = rtl_str_getLength(pCharsetName) + 7;
    3285             :                     // '=?', '?Q?', '?='
    3286             : 
    3287           0 :                 switch (m_ePrevCoding)
    3288             :                 {
    3289             :                     case CODING_QUOTED:
    3290           0 :                         m_rSink << '"';
    3291             :                     case CODING_NONE:
    3292           0 :                         if (m_eInitialSpace == SPACE_ENCODED
    3293             :                             && m_nExtraSpaces == 0)
    3294           0 :                             m_nExtraSpaces = 1;
    3295           0 :                         nSize += nWrapperSize;
    3296           0 :                         for (; m_nExtraSpaces > 1; --m_nExtraSpaces)
    3297             :                         {
    3298           0 :                             if (m_rSink.getColumn() >= m_rSink.getLineLengthLimit())
    3299           0 :                                 m_rSink << INetMIMEOutputSink::endl;
    3300           0 :                             m_rSink << ' ';
    3301             :                         }
    3302           0 :                         if (m_nExtraSpaces == 1)
    3303             :                         {
    3304           0 :                             if (m_rSink.getColumn() + nSize >= m_rSink.getLineLengthLimit())
    3305           0 :                                 m_rSink << INetMIMEOutputSink::endl;
    3306           0 :                             m_rSink << ' ';
    3307             :                         }
    3308           0 :                         m_rSink << "=?" << pCharsetName << "?Q?";
    3309           0 :                         break;
    3310             : 
    3311             :                     case CODING_ENCODED:
    3312           0 :                         if (m_ePrevMIMEEncoding != eMIMEEncoding
    3313           0 :                             || m_rSink.getColumn() + m_nExtraSpaces + nSize
    3314           0 :                                    > m_rSink.getLineLengthLimit() - 2)
    3315             :                         {
    3316           0 :                             m_rSink << "?=";
    3317           0 :                             if (m_rSink.getColumn() + nWrapperSize
    3318             :                                         + m_nExtraSpaces + nSize
    3319           0 :                                     > m_rSink.getLineLengthLimit() - 1)
    3320           0 :                                 m_rSink << INetMIMEOutputSink::endl;
    3321           0 :                             m_rSink << " =?" << pCharsetName << "?Q?";
    3322             :                         }
    3323           0 :                         while (m_nExtraSpaces-- > 0)
    3324             :                         {
    3325           0 :                             if (m_rSink.getColumn()
    3326           0 :                                     > m_rSink.getLineLengthLimit() - 3)
    3327           0 :                                 m_rSink << "?=" << INetMIMEOutputSink::endl
    3328           0 :                                         << " =?" << pCharsetName << "?Q?";
    3329           0 :                             m_rSink << '_';
    3330             :                         }
    3331           0 :                         break;
    3332             : 
    3333             :                     case CODING_ENCODED_TERMINATED:
    3334           0 :                         if (m_rSink.getColumn() + nWrapperSize
    3335             :                                     + m_nExtraSpaces + nSize
    3336           0 :                                 > m_rSink.getLineLengthLimit() - 1)
    3337           0 :                             m_rSink << INetMIMEOutputSink::endl;
    3338           0 :                         m_rSink << " =?" << pCharsetName << "?Q?";
    3339           0 :                         while (m_nExtraSpaces-- > 0)
    3340             :                         {
    3341           0 :                             if (m_rSink.getColumn()
    3342           0 :                                     > m_rSink.getLineLengthLimit() - 3)
    3343           0 :                                 m_rSink << "?=" << INetMIMEOutputSink::endl
    3344           0 :                                         << " =?" << pCharsetName << "?Q?";
    3345           0 :                             m_rSink << '_';
    3346             :                         }
    3347           0 :                         break;
    3348             :                 }
    3349             : 
    3350             :                 // The non UTF-8 code will only work for stateless single byte
    3351             :                 // character encodings (see also above):
    3352           0 :                 if (eMIMEEncoding == RTL_TEXTENCODING_UTF8)
    3353             :                 {
    3354           0 :                     bool bInitial = true;
    3355           0 :                     for (sal_Unicode const * p = m_pBuffer;
    3356             :                          p != m_pBufferEnd;)
    3357             :                     {
    3358             :                         sal_uInt32 nUTF32
    3359           0 :                             = INetMIME::getUTF32Character(p, m_pBufferEnd);
    3360           0 :                         bool bEscape = needsEncodedWordEscape(nUTF32);
    3361             :                         sal_uInt32 nWidth
    3362             :                             = bEscape ?
    3363           0 :                                   3 * INetMIME::getUTF8OctetCount(nUTF32) : 1;
    3364             :                             // only US-ASCII characters (that are converted to
    3365             :                             // a single byte by UTF-8) need no encoded word
    3366             :                             // escapes...
    3367           0 :                         if (!bInitial
    3368           0 :                             && m_rSink.getColumn() + nWidth + 2
    3369           0 :                                    > m_rSink.getLineLengthLimit())
    3370           0 :                             m_rSink << "?=" << INetMIMEOutputSink::endl
    3371           0 :                                     << " =?" << pCharsetName << "?Q?";
    3372           0 :                         if (bEscape)
    3373             :                         {
    3374             :                             DBG_ASSERT(
    3375             :                                 nUTF32 < 0x10FFFF,
    3376             :                                 "INetMIMEEncodedWordOutputSink::finish():"
    3377             :                                     " Bad char");
    3378           0 :                             if (nUTF32 < 0x80)
    3379             :                                 INetMIME::writeEscapeSequence(m_rSink,
    3380           0 :                                                               nUTF32);
    3381           0 :                             else if (nUTF32 < 0x800)
    3382             :                             {
    3383             :                                 INetMIME::writeEscapeSequence(m_rSink,
    3384             :                                                               (nUTF32 >> 6)
    3385           0 :                                                                   | 0xC0);
    3386             :                                 INetMIME::writeEscapeSequence(m_rSink,
    3387             :                                                               (nUTF32 & 0x3F)
    3388           0 :                                                                   | 0x80);
    3389             :                             }
    3390           0 :                             else if (nUTF32 < 0x10000)
    3391             :                             {
    3392             :                                 INetMIME::writeEscapeSequence(m_rSink,
    3393             :                                                               (nUTF32 >> 12)
    3394           0 :                                                                   | 0xE0);
    3395             :                                 INetMIME::writeEscapeSequence(m_rSink,
    3396             :                                                               ((nUTF32 >> 6)
    3397             :                                                                       & 0x3F)
    3398           0 :                                                                   | 0x80);
    3399             :                                 INetMIME::writeEscapeSequence(m_rSink,
    3400             :                                                               (nUTF32 & 0x3F)
    3401           0 :                                                                   | 0x80);
    3402             :                             }
    3403             :                             else
    3404             :                             {
    3405             :                                 INetMIME::writeEscapeSequence(m_rSink,
    3406             :                                                               (nUTF32 >> 18)
    3407           0 :                                                                   | 0xF0);
    3408             :                                 INetMIME::writeEscapeSequence(m_rSink,
    3409             :                                                               ((nUTF32 >> 12)
    3410             :                                                                       & 0x3F)
    3411           0 :                                                                   | 0x80);
    3412             :                                 INetMIME::writeEscapeSequence(m_rSink,
    3413             :                                                               ((nUTF32 >> 6)
    3414             :                                                                       & 0x3F)
    3415           0 :                                                                   | 0x80);
    3416             :                                 INetMIME::writeEscapeSequence(m_rSink,
    3417             :                                                               (nUTF32 & 0x3F)
    3418           0 :                                                                   | 0x80);
    3419             :                             }
    3420             :                         }
    3421             :                         else
    3422           0 :                             m_rSink << sal_Char(nUTF32);
    3423           0 :                         bInitial = false;
    3424             :                     }
    3425             :                 }
    3426             :                 else
    3427             :                 {
    3428           0 :                     for (sal_Size k = 0; k < nTargetSize; ++k)
    3429             :                     {
    3430           0 :                         sal_uInt32 nUCS4 = sal_uChar(pTargetBuffer[k]);
    3431           0 :                         bool bEscape = needsEncodedWordEscape(nUCS4);
    3432           0 :                         if (k > 0
    3433           0 :                             && m_rSink.getColumn() + (bEscape ? 5 : 3)
    3434           0 :                                    > m_rSink.getLineLengthLimit())
    3435           0 :                             m_rSink << "?=" << INetMIMEOutputSink::endl
    3436           0 :                                     << " =?" << pCharsetName << "?Q?";
    3437           0 :                         if (bEscape)
    3438           0 :                             INetMIME::writeEscapeSequence(m_rSink, nUCS4);
    3439             :                         else
    3440           0 :                             m_rSink << sal_Char(nUCS4);
    3441             :                     }
    3442           0 :                     delete[] pTargetBuffer;
    3443             :                 }
    3444             : 
    3445           0 :                 if (bWriteTrailer)
    3446             :                 {
    3447           0 :                     m_rSink << "?=";
    3448           0 :                     m_eCoding = CODING_ENCODED_TERMINATED;
    3449             :                 }
    3450             : 
    3451           0 :                 m_ePrevMIMEEncoding = eMIMEEncoding;
    3452           0 :                 break;
    3453             :             }
    3454             : 
    3455             :             default:
    3456             :                 OSL_ASSERT(false);
    3457           0 :                 break;
    3458             :         }
    3459             :     }
    3460             : 
    3461           0 :     m_eInitialSpace = SPACE_NO;
    3462           0 :     m_nExtraSpaces = 0;
    3463           0 :     m_pEncodingList->reset();
    3464           0 :     m_pBufferEnd = m_pBuffer;
    3465           0 :     m_ePrevCoding = m_eCoding;
    3466           0 :     m_eCoding = CODING_NONE;
    3467           0 :     m_nQuotedEscaped = 0;
    3468           0 :     m_eEncodedWordState = STATE_INITIAL;
    3469           0 : }
    3470             : 
    3471           0 : INetMIMEEncodedWordOutputSink::~INetMIMEEncodedWordOutputSink()
    3472             : {
    3473           0 :     rtl_freeMemory(m_pBuffer);
    3474           0 :     delete m_pEncodingList;
    3475           0 : }
    3476             : 
    3477             : INetMIMEEncodedWordOutputSink &
    3478           0 : INetMIMEEncodedWordOutputSink::operator <<(sal_uInt32 nChar)
    3479             : {
    3480           0 :     if (nChar == ' ')
    3481             :     {
    3482           0 :         if (m_pBufferEnd != m_pBuffer)
    3483           0 :             finish(false);
    3484           0 :         ++m_nExtraSpaces;
    3485             :     }
    3486             :     else
    3487             :     {
    3488             :         // Check for an already encoded word:
    3489           0 :         switch (m_eEncodedWordState)
    3490             :         {
    3491             :             case STATE_INITIAL:
    3492           0 :                 if (nChar == '=')
    3493           0 :                     m_eEncodedWordState = STATE_FIRST_EQUALS;
    3494             :                 else
    3495           0 :                     m_eEncodedWordState = STATE_BAD;
    3496           0 :                 break;
    3497             : 
    3498             :             case STATE_FIRST_EQUALS:
    3499           0 :                 if (nChar == '?')
    3500           0 :                     m_eEncodedWordState = STATE_FIRST_EQUALS;
    3501             :                 else
    3502           0 :                     m_eEncodedWordState = STATE_BAD;
    3503           0 :                 break;
    3504             : 
    3505             :             case STATE_FIRST_QUESTION:
    3506           0 :                 if (INetMIME::isEncodedWordTokenChar(nChar))
    3507           0 :                     m_eEncodedWordState = STATE_CHARSET;
    3508             :                 else
    3509           0 :                     m_eEncodedWordState = STATE_BAD;
    3510           0 :                 break;
    3511             : 
    3512             :             case STATE_CHARSET:
    3513           0 :                 if (nChar == '?')
    3514           0 :                     m_eEncodedWordState = STATE_SECOND_QUESTION;
    3515           0 :                 else if (!INetMIME::isEncodedWordTokenChar(nChar))
    3516           0 :                     m_eEncodedWordState = STATE_BAD;
    3517           0 :                 break;
    3518             : 
    3519             :             case STATE_SECOND_QUESTION:
    3520           0 :                 if (nChar == 'B' || nChar == 'Q'
    3521             :                     || nChar == 'b' || nChar == 'q')
    3522           0 :                     m_eEncodedWordState = STATE_ENCODING;
    3523             :                 else
    3524           0 :                     m_eEncodedWordState = STATE_BAD;
    3525           0 :                 break;
    3526             : 
    3527             :             case STATE_ENCODING:
    3528           0 :                 if (nChar == '?')
    3529           0 :                     m_eEncodedWordState = STATE_THIRD_QUESTION;
    3530             :                 else
    3531           0 :                     m_eEncodedWordState = STATE_BAD;
    3532           0 :                 break;
    3533             : 
    3534             :             case STATE_THIRD_QUESTION:
    3535           0 :                 if (INetMIME::isVisible(nChar) && nChar != '?')
    3536           0 :                     m_eEncodedWordState = STATE_ENCODED_TEXT;
    3537             :                 else
    3538           0 :                     m_eEncodedWordState = STATE_BAD;
    3539           0 :                 break;
    3540             : 
    3541             :             case STATE_ENCODED_TEXT:
    3542           0 :                 if (nChar == '?')
    3543           0 :                     m_eEncodedWordState = STATE_FOURTH_QUESTION;
    3544           0 :                 else if (!INetMIME::isVisible(nChar))
    3545           0 :                     m_eEncodedWordState = STATE_BAD;
    3546           0 :                 break;
    3547             : 
    3548             :             case STATE_FOURTH_QUESTION:
    3549           0 :                 if (nChar == '=')
    3550           0 :                     m_eEncodedWordState = STATE_SECOND_EQUALS;
    3551             :                 else
    3552           0 :                     m_eEncodedWordState = STATE_BAD;
    3553           0 :                 break;
    3554             : 
    3555             :             case STATE_SECOND_EQUALS:
    3556           0 :                 m_eEncodedWordState = STATE_BAD;
    3557           0 :                 break;
    3558             : 
    3559             :             case STATE_BAD:
    3560           0 :                 break;
    3561             :         }
    3562             : 
    3563             :         // Update encoding:
    3564           0 :         m_pEncodingList->includes(nChar);
    3565             : 
    3566             :         // Update coding:
    3567             :         enum { TENQ = 1,   // CONTEXT_TEXT, CODING_ENCODED
    3568             :                CENQ = 2,   // CONTEXT_COMMENT, CODING_ENCODED
    3569             :                PQTD = 4,   // CONTEXT_PHRASE, CODING_QUOTED
    3570             :                PENQ = 8 }; // CONTEXT_PHRASE, CODING_ENCODED
    3571             :         static const sal_Char aMinimal[128]
    3572             :             = { TENQ | CENQ        | PENQ,   // 0x00
    3573             :                 TENQ | CENQ        | PENQ,   // 0x01
    3574             :                 TENQ | CENQ        | PENQ,   // 0x02
    3575             :                 TENQ | CENQ        | PENQ,   // 0x03
    3576             :                 TENQ | CENQ        | PENQ,   // 0x04
    3577             :                 TENQ | CENQ        | PENQ,   // 0x05
    3578             :                 TENQ | CENQ        | PENQ,   // 0x06
    3579             :                 TENQ | CENQ        | PENQ,   // 0x07
    3580             :                 TENQ | CENQ        | PENQ,   // 0x08
    3581             :                 TENQ | CENQ        | PENQ,   // 0x09
    3582             :                 TENQ | CENQ        | PENQ,   // 0x0A
    3583             :                 TENQ | CENQ        | PENQ,   // 0x0B
    3584             :                 TENQ | CENQ        | PENQ,   // 0x0C
    3585             :                 TENQ | CENQ        | PENQ,   // 0x0D
    3586             :                 TENQ | CENQ        | PENQ,   // 0x0E
    3587             :                 TENQ | CENQ        | PENQ,   // 0x0F
    3588             :                 TENQ | CENQ        | PENQ,   // 0x10
    3589             :                 TENQ | CENQ        | PENQ,   // 0x11
    3590             :                 TENQ | CENQ        | PENQ,   // 0x12
    3591             :                 TENQ | CENQ        | PENQ,   // 0x13
    3592             :                 TENQ | CENQ        | PENQ,   // 0x14
    3593             :                 TENQ | CENQ        | PENQ,   // 0x15
    3594             :                 TENQ | CENQ        | PENQ,   // 0x16
    3595             :                 TENQ | CENQ        | PENQ,   // 0x17
    3596             :                 TENQ | CENQ        | PENQ,   // 0x18
    3597             :                 TENQ | CENQ        | PENQ,   // 0x19
    3598             :                 TENQ | CENQ        | PENQ,   // 0x1A
    3599             :                 TENQ | CENQ        | PENQ,   // 0x1B
    3600             :                 TENQ | CENQ        | PENQ,   // 0x1C
    3601             :                 TENQ | CENQ        | PENQ,   // 0x1D
    3602             :                 TENQ | CENQ        | PENQ,   // 0x1E
    3603             :                 TENQ | CENQ        | PENQ,   // 0x1F
    3604             :                                         0,   // ' '
    3605             :                                         0,   // '!'
    3606             :                               PQTD       ,   // '"'
    3607             :                                         0,   // '#'
    3608             :                                         0,   // '$'
    3609             :                                         0,   // '%'
    3610             :                                         0,   // '&'
    3611             :                                         0,   // '''
    3612             :                        CENQ | PQTD       ,   // '('
    3613             :                        CENQ | PQTD       ,   // ')'
    3614             :                                         0,   // '*'
    3615             :                                         0,   // '+'
    3616             :                               PQTD       ,   // ','
    3617             :                                         0,   // '-'
    3618             :                               PQTD       ,   // '.'
    3619             :                                         0,   // '/'
    3620             :                                         0,   // '0'
    3621             :                                         0,   // '1'
    3622             :                                         0,   // '2'
    3623             :                                         0,   // '3'
    3624             :                                         0,   // '4'
    3625             :                                         0,   // '5'
    3626             :                                         0,   // '6'
    3627             :                                         0,   // '7'
    3628             :                                         0,   // '8'
    3629             :                                         0,   // '9'
    3630             :                               PQTD       ,   // ':'
    3631             :                               PQTD       ,   // ';'
    3632             :                               PQTD       ,   // '<'
    3633             :                                         0,   // '='
    3634             :                               PQTD       ,   // '>'
    3635             :                                         0,   // '?'
    3636             :                               PQTD       ,   // '@'
    3637             :                                         0,   // 'A'
    3638             :                                         0,   // 'B'
    3639             :                                         0,   // 'C'
    3640             :                                         0,   // 'D'
    3641             :                                         0,   // 'E'
    3642             :                                         0,   // 'F'
    3643             :                                         0,   // 'G'
    3644             :                                         0,   // 'H'
    3645             :                                         0,   // 'I'
    3646             :                                         0,   // 'J'
    3647             :                                         0,   // 'K'
    3648             :                                         0,   // 'L'
    3649             :                                         0,   // 'M'
    3650             :                                         0,   // 'N'
    3651             :                                         0,   // 'O'
    3652             :                                         0,   // 'P'
    3653             :                                         0,   // 'Q'
    3654             :                                         0,   // 'R'
    3655             :                                         0,   // 'S'
    3656             :                                         0,   // 'T'
    3657             :                                         0,   // 'U'
    3658             :                                         0,   // 'V'
    3659             :                                         0,   // 'W'
    3660             :                                         0,   // 'X'
    3661             :                                         0,   // 'Y'
    3662             :                                         0,   // 'Z'
    3663             :                               PQTD       ,   // '['
    3664             :                        CENQ | PQTD       ,   // '\'
    3665             :                               PQTD       ,   // ']'
    3666             :                                         0,   // '^'
    3667             :                                         0,   // '_'
    3668             :                                         0,   // '`'
    3669             :                                         0,   // 'a'
    3670             :                                         0,   // 'b'
    3671             :                                         0,   // 'c'
    3672             :                                         0,   // 'd'
    3673             :                                         0,   // 'e'
    3674             :                                         0,   // 'f'
    3675             :                                         0,   // 'g'
    3676             :                                         0,   // 'h'
    3677             :                                         0,   // 'i'
    3678             :                                         0,   // 'j'
    3679             :                                         0,   // 'k'
    3680             :                                         0,   // 'l'
    3681             :                                         0,   // 'm'
    3682             :                                         0,   // 'n'
    3683             :                                         0,   // 'o'
    3684             :                                         0,   // 'p'
    3685             :                                         0,   // 'q'
    3686             :                                         0,   // 'r'
    3687             :                                         0,   // 's'
    3688             :                                         0,   // 't'
    3689             :                                         0,   // 'u'
    3690             :                                         0,   // 'v'
    3691             :                                         0,   // 'w'
    3692             :                                         0,   // 'x'
    3693             :                                         0,   // 'y'
    3694             :                                         0,   // 'z'
    3695             :                                         0,   // '{'
    3696             :                                         0,   // '|'
    3697             :                                         0,   // '}'
    3698             :                                         0,   // '~'
    3699             :                 TENQ | CENQ        | PENQ }; // DEL
    3700           0 :         Coding eNewCoding = !INetMIME::isUSASCII(nChar) ? CODING_ENCODED :
    3701             :                             m_eContext == CONTEXT_PHRASE ?
    3702           0 :                                 Coding(aMinimal[nChar] >> 2) :
    3703           0 :                             aMinimal[nChar] & m_eContext ? CODING_ENCODED :
    3704           0 :                                                            CODING_NONE;
    3705           0 :         if (eNewCoding > m_eCoding)
    3706           0 :             m_eCoding = eNewCoding;
    3707           0 :         if (m_eCoding == CODING_QUOTED
    3708           0 :             && INetMIME::needsQuotedStringEscape(nChar))
    3709           0 :             ++m_nQuotedEscaped;
    3710             : 
    3711             :         // Append to buffer:
    3712           0 :         if (sal_uInt32(m_pBufferEnd - m_pBuffer) == m_nBufferSize)
    3713             :         {
    3714             :             m_pBuffer
    3715             :                 = static_cast< sal_Unicode * >(
    3716             :                       rtl_reallocateMemory(m_pBuffer,
    3717             :                                            (m_nBufferSize + BUFFER_SIZE)
    3718           0 :                                                * sizeof (sal_Unicode)));
    3719           0 :             m_pBufferEnd = m_pBuffer + m_nBufferSize;
    3720           0 :             m_nBufferSize += BUFFER_SIZE;
    3721             :         }
    3722           0 :         *m_pBufferEnd++ = sal_Unicode(nChar);
    3723             :     }
    3724           0 :     return *this;
    3725             : }
    3726             : 
    3727             : //  INetContentTypeParameterList
    3728             : 
    3729           0 : void INetContentTypeParameterList::Clear()
    3730             : {
    3731           0 :     maEntries.clear();
    3732           0 : }
    3733             : 
    3734             : const INetContentTypeParameter *
    3735           0 : INetContentTypeParameterList::find(const rtl::OString& rAttribute) const
    3736             : {
    3737           0 :     boost::ptr_vector<INetContentTypeParameter>::const_iterator iter;
    3738           0 :     for (iter = maEntries.begin(); iter != maEntries.end(); ++iter)
    3739             :     {
    3740           0 :         if (iter->m_sAttribute.equalsIgnoreAsciiCase(rAttribute))
    3741           0 :             return &(*iter);
    3742             :     }
    3743             : 
    3744           0 :     return NULL;
    3745             : }
    3746             : 
    3747             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10