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

Generated by: LCOV version 1.10