LCOV - code coverage report
Current view: top level - tools/source/inet - inetmime.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 1528 0.0 %
Date: 2014-04-14 Functions: 0 55 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <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             : #include <rtl/character.hxx>
      28             : 
      29             : namespace unnamed_tools_inetmime {} using namespace unnamed_tools_inetmime;
      30             :     // unnamed namespaces don't work well yet
      31             : 
      32             : namespace unnamed_tools_inetmime {
      33             : 
      34             : class Charset
      35             : {
      36             :     rtl_TextEncoding m_eEncoding;
      37             :     const sal_uInt32 * m_pRanges;
      38             : 
      39             : public:
      40             :     inline Charset(rtl_TextEncoding eTheEncoding,
      41             :                    const sal_uInt32 * pTheRanges);
      42             : 
      43           0 :     rtl_TextEncoding getEncoding() const { return m_eEncoding; }
      44             : 
      45             :     bool contains(sal_uInt32 nChar) const;
      46             : };
      47             : 
      48           0 : inline Charset::Charset(rtl_TextEncoding eTheEncoding,
      49             :                         const sal_uInt32 * pTheRanges):
      50             :     m_eEncoding(eTheEncoding),
      51           0 :     m_pRanges(pTheRanges)
      52             : {
      53             :     DBG_ASSERT(m_pRanges, "Charset::Charset(): Bad ranges");
      54           0 : }
      55             : 
      56             : void appendISO88591(OUString & rText, sal_Char const * pBegin,
      57             :                     sal_Char const * pEnd);
      58             : 
      59             : }
      60             : 
      61             : class INetMIMECharsetList_Impl
      62             : {
      63             :     struct Node
      64             :     {
      65             :         Charset m_aCharset;
      66             :         bool m_bDisabled;
      67             :         Node * m_pNext;
      68             : 
      69             :         inline Node(const Charset & rTheCharset, bool bTheDisabled,
      70             :                     Node * pTheNext);
      71             :     };
      72             : 
      73             :     Node * m_pFirst;
      74             : 
      75             : public:
      76           0 :     INetMIMECharsetList_Impl(): m_pFirst(0) {}
      77             : 
      78             :     ~INetMIMECharsetList_Impl();
      79             : 
      80           0 :     void prepend(const Charset & rCharset)
      81           0 :     { m_pFirst = new Node(rCharset, false, m_pFirst); }
      82             : 
      83             :     void includes(sal_uInt32 nChar);
      84             : 
      85             :     rtl_TextEncoding getPreferredEncoding(rtl_TextEncoding eDefault
      86             :                                               = RTL_TEXTENCODING_DONTKNOW)
      87             :         const;
      88             : 
      89             :     void reset();
      90             : };
      91             : 
      92           0 : inline INetMIMECharsetList_Impl::Node::Node(const Charset & rTheCharset,
      93             :                                             bool bTheDisabled,
      94             :                                             Node * pTheNext):
      95             :     m_aCharset(rTheCharset),
      96             :     m_bDisabled(bTheDisabled),
      97           0 :     m_pNext(pTheNext)
      98           0 : {}
      99             : 
     100             : namespace unnamed_tools_inetmime {
     101             : 
     102           0 : struct Parameter
     103             : {
     104             :     Parameter * m_pNext;
     105             :     OString m_aAttribute;
     106             :     OString m_aCharset;
     107             :     OString m_aLanguage;
     108             :     OString m_aValue;
     109             :     sal_uInt32 m_nSection;
     110             :     bool m_bExtended;
     111             : 
     112             :     inline Parameter(Parameter * pTheNext, const OString& rTheAttribute,
     113             :                      const OString& rTheCharset,
     114             :                      const OString& rTheLanguage,
     115             :                      const OString& rTheValue, sal_uInt32 nTheSection,
     116             :                      bool bTheExtended);
     117             : };
     118             : 
     119           0 : inline Parameter::Parameter(Parameter * pTheNext,
     120             :                             const OString& rTheAttribute,
     121             :                             const OString& rTheCharset,
     122             :                             const OString& rTheLanguage,
     123             :                             const OString& rTheValue,
     124             :                             sal_uInt32 nTheSection, bool bTheExtended):
     125             :     m_pNext(pTheNext),
     126             :     m_aAttribute(rTheAttribute),
     127             :     m_aCharset(rTheCharset),
     128             :     m_aLanguage(rTheLanguage),
     129             :     m_aValue(rTheValue),
     130             :     m_nSection(nTheSection),
     131           0 :     m_bExtended(bTheExtended)
     132           0 : {}
     133             : 
     134             : struct ParameterList
     135             : {
     136             :     Parameter * m_pList;
     137             : 
     138           0 :     ParameterList(): m_pList(0) {}
     139             : 
     140             :     inline ~ParameterList();
     141             : 
     142             :     Parameter ** find(const OString& rAttribute, sal_uInt32 nSection,
     143             :                       bool & rPresent);
     144             : };
     145             : 
     146           0 : inline ParameterList::~ParameterList()
     147             : {
     148           0 :     while (m_pList)
     149             :     {
     150           0 :         Parameter * pNext = m_pList->m_pNext;
     151           0 :         delete m_pList;
     152           0 :         m_pList = pNext;
     153             :     }
     154           0 : }
     155             : 
     156             : bool parseParameters(ParameterList const & rInput,
     157             :                      INetContentTypeParameterList * pOutput);
     158             : 
     159             : }
     160             : 
     161             : //  Charset
     162             : 
     163           0 : bool Charset::contains(sal_uInt32 nChar) const
     164             : {
     165           0 :     for (const sal_uInt32 * p = m_pRanges;;)
     166             :     {
     167           0 :         if (nChar < *p++)
     168           0 :             return false;
     169           0 :         if (nChar <= *p++)
     170           0 :             return true;
     171           0 :     }
     172             : }
     173             : 
     174             : //  appendISO88591
     175             : 
     176             : namespace unnamed_tools_inetmime {
     177             : 
     178           0 : void appendISO88591(OUString & rText, sal_Char const * pBegin,
     179             :                     sal_Char const * pEnd)
     180             : {
     181           0 :     sal_Int32 nLength = pEnd - pBegin;
     182           0 :     sal_Unicode * pBuffer = new sal_Unicode[nLength];
     183           0 :     for (sal_Unicode * p = pBuffer; pBegin != pEnd;)
     184           0 :         *p++ = static_cast<unsigned char>(*pBegin++);
     185           0 :     rText += OUString(pBuffer, nLength);
     186           0 :     delete[] pBuffer;
     187           0 : }
     188             : 
     189             : }
     190             : 
     191             : //  INetMIMECharsetList_Impl
     192             : 
     193           0 : INetMIMECharsetList_Impl::~INetMIMECharsetList_Impl()
     194             : {
     195           0 :     while (m_pFirst)
     196             :     {
     197           0 :         Node * pRemove = m_pFirst;
     198           0 :         m_pFirst = m_pFirst->m_pNext;
     199           0 :         delete pRemove;
     200             :     }
     201           0 : }
     202             : 
     203           0 : void INetMIMECharsetList_Impl::includes(sal_uInt32 nChar)
     204             : {
     205           0 :     for (Node * p = m_pFirst; p; p = p->m_pNext)
     206           0 :         if (!(p->m_bDisabled || p->m_aCharset.contains(nChar)))
     207           0 :             p->m_bDisabled = true;
     208           0 : }
     209             : 
     210           0 : rtl_TextEncoding INetMIMECharsetList_Impl::getPreferredEncoding(rtl_TextEncoding eDefault)
     211             :     const
     212             : {
     213           0 :     for (Node * p = m_pFirst; p; p = p->m_pNext)
     214           0 :         if (!p->m_bDisabled)
     215           0 :             return p->m_aCharset.getEncoding();
     216           0 :     return eDefault;
     217             : }
     218             : 
     219           0 : void INetMIMECharsetList_Impl::reset()
     220             : {
     221           0 :     for (Node * p = m_pFirst; p; p = p->m_pNext)
     222           0 :         p->m_bDisabled = false;
     223           0 : }
     224             : 
     225             : //  ParameterList
     226             : 
     227           0 : Parameter ** ParameterList::find(const OString& rAttribute,
     228             :                                  sal_uInt32 nSection, bool & rPresent)
     229             : {
     230           0 :     Parameter ** p = &m_pList;
     231           0 :     for (; *p; p = &(*p)->m_pNext)
     232             :     {
     233           0 :         sal_Int32 nCompare = rAttribute.compareTo((*p)->m_aAttribute);
     234           0 :         if (nCompare > 0)
     235           0 :             break;
     236           0 :         else if (nCompare == 0)
     237             :         {
     238           0 :             if (nSection > (*p)->m_nSection)
     239           0 :                 break;
     240           0 :             else if (nSection == (*p)->m_nSection)
     241             :             {
     242           0 :                 rPresent = true;
     243           0 :                 return p;
     244             :             }
     245             :         }
     246             :     }
     247           0 :     rPresent = false;
     248           0 :     return p;
     249             : }
     250             : 
     251             : //  parseParameters
     252             : 
     253             : namespace unnamed_tools_inetmime {
     254             : 
     255           0 : bool parseParameters(ParameterList const & rInput,
     256             :                      INetContentTypeParameterList * pOutput)
     257             : {
     258           0 :     if (pOutput)
     259           0 :         pOutput->Clear();
     260             : 
     261           0 :     Parameter * pPrev = 0;
     262           0 :     for (Parameter * p = rInput.m_pList; p; p = p->m_pNext)
     263             :     {
     264           0 :         if (p->m_nSection > 0
     265           0 :             && (!pPrev
     266           0 :                 || pPrev->m_nSection != p->m_nSection - 1
     267           0 :                 || pPrev->m_aAttribute != p->m_aAttribute))
     268           0 :             return false;
     269           0 :         pPrev = p;
     270             :     }
     271             : 
     272           0 :     if (pOutput)
     273           0 :         for (Parameter * p = rInput.m_pList; p;)
     274             :         {
     275           0 :             bool bCharset = !p->m_aCharset.isEmpty();
     276           0 :             rtl_TextEncoding eEncoding = RTL_TEXTENCODING_DONTKNOW;
     277           0 :             if (bCharset)
     278             :                 eEncoding
     279             :                     = INetMIME::getCharsetEncoding(p->m_aCharset.getStr(),
     280           0 :                                                    p->m_aCharset.getStr()
     281             :                                                        + rInput.m_pList->
     282             :                                                              m_aCharset.
     283           0 :                                                                  getLength());
     284           0 :             OUString aValue;
     285           0 :             bool bBadEncoding = false;
     286           0 :             Parameter * pNext = p;
     287           0 :             do
     288             :             {
     289             :                 sal_Size nSize;
     290             :                 sal_Unicode * pUnicode
     291             :                     = INetMIME::convertToUnicode(pNext->m_aValue.getStr(),
     292           0 :                                                  pNext->m_aValue.getStr()
     293           0 :                                                      + pNext->m_aValue.getLength(),
     294           0 :                                                  bCharset && p->m_bExtended ?
     295             :                                                      eEncoding :
     296             :                                                      RTL_TEXTENCODING_UTF8,
     297           0 :                                                  nSize);
     298           0 :                 if (!pUnicode && !(bCharset && p->m_bExtended))
     299             :                     pUnicode = INetMIME::convertToUnicode(
     300             :                                    pNext->m_aValue.getStr(),
     301           0 :                                    pNext->m_aValue.getStr()
     302           0 :                                        + pNext->m_aValue.getLength(),
     303           0 :                                    RTL_TEXTENCODING_ISO_8859_1, nSize);
     304           0 :                 if (!pUnicode)
     305             :                 {
     306           0 :                     bBadEncoding = true;
     307           0 :                     break;
     308             :                 }
     309           0 :                 aValue += OUString(pUnicode, static_cast<sal_Int32>(nSize));
     310           0 :                 delete[] pUnicode;
     311           0 :                 pNext = pNext->m_pNext;
     312             :             }
     313           0 :             while (pNext && pNext->m_nSection > 0);
     314           0 :             if (bBadEncoding)
     315             :             {
     316           0 :                 aValue = OUString();
     317           0 :                 for (pNext = p;;)
     318             :                 {
     319           0 :                     if (pNext->m_bExtended)
     320             :                     {
     321           0 :                         for (sal_Int32 i = 0; i < pNext->m_aValue.getLength(); ++i)
     322           0 :                             aValue += OUString(sal_Unicode(
     323             :                                 sal_Unicode(
     324           0 :                                     static_cast<unsigned char>(pNext->m_aValue[i]))
     325           0 :                                 | 0xF800));
     326             :                     }
     327             :                     else
     328             :                     {
     329           0 :                         for (sal_Int32 i = 0; i < pNext->m_aValue.getLength(); ++i)
     330           0 :                             aValue += OUString( sal_Unicode(static_cast<unsigned char>(pNext->m_aValue[i])) );
     331             :                     }
     332           0 :                     pNext = pNext->m_pNext;
     333           0 :                     if (!pNext || pNext->m_nSection == 0)
     334             :                         break;
     335           0 :                 };
     336             :             }
     337             :             pOutput->Append(new INetContentTypeParameter(p->m_aAttribute,
     338             :                                                              p->m_aCharset,
     339             :                                                              p->m_aLanguage,
     340             :                                                              aValue,
     341           0 :                                                              !bBadEncoding));
     342           0 :             p = pNext;
     343           0 :         }
     344           0 :     return true;
     345             : }
     346             : 
     347             : }
     348             : 
     349             : //  INetMIME
     350             : 
     351             : // static
     352           0 : bool INetMIME::isAtomChar(sal_uInt32 nChar)
     353             : {
     354             :     static const bool aMap[128]
     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, false, false, false, false, false, false, false,
     359             :             false,  true, false,  true,  true,  true,  true,  true, // !"#$%&'
     360             :             false, false,  true,  true, false,  true, false,  true, //()*+,-./
     361             :              true,  true,  true,  true,  true,  true,  true,  true, //01234567
     362             :              true,  true, false, false, false,  true, false,  true, //89:;<=>?
     363             :             false,  true,  true,  true,  true,  true,  true,  true, //@ABCDEFG
     364             :              true,  true,  true,  true,  true,  true,  true,  true, //HIJKLMNO
     365             :              true,  true,  true,  true,  true,  true,  true,  true, //PQRSTUVW
     366             :              true,  true,  true, false, false, false,  true,  true, //XYZ[\]^_
     367             :              true,  true,  true,  true,  true,  true,  true,  true, //`abcdefg
     368             :              true,  true,  true,  true,  true,  true,  true,  true, //hijklmno
     369             :              true,  true,  true,  true,  true,  true,  true,  true, //pqrstuvw
     370             :              true,  true,  true,  true,  true,  true,  true, false  //xyz{|}~
     371             :           };
     372           0 :     return rtl::isAscii(nChar) && aMap[nChar];
     373             : }
     374             : 
     375             : // static
     376           0 : bool INetMIME::isTokenChar(sal_uInt32 nChar)
     377             : {
     378             :     static const bool aMap[128]
     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, false, false, false, false, false, false, false,
     383             :             false,  true, false,  true,  true,  true,  true,  true, // !"#$%&'
     384             :             false, false,  true,  true, false,  true,  true, false, //()*+,-./
     385             :              true,  true,  true,  true,  true,  true,  true,  true, //01234567
     386             :              true,  true, false, false, false, false, false, false, //89:;<=>?
     387             :             false,  true,  true,  true,  true,  true,  true,  true, //@ABCDEFG
     388             :              true,  true,  true,  true,  true,  true,  true,  true, //HIJKLMNO
     389             :              true,  true,  true,  true,  true,  true,  true,  true, //PQRSTUVW
     390             :              true,  true,  true, false, false, false,  true,  true, //XYZ[\]^_
     391             :              true,  true,  true,  true,  true,  true,  true,  true, //`abcdefg
     392             :              true,  true,  true,  true,  true,  true,  true,  true, //hijklmno
     393             :              true,  true,  true,  true,  true,  true,  true,  true, //pqrstuvw
     394             :              true,  true,  true,  true,  true,  true,  true, false  //xyz{|}~
     395             :           };
     396           0 :     return rtl::isAscii(nChar) && aMap[nChar];
     397             : }
     398             : 
     399             : // static
     400           0 : bool INetMIME::isEncodedWordTokenChar(sal_uInt32 nChar)
     401             : {
     402             :     static const bool aMap[128]
     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, false, false, false, false, false, false, false,
     407             :             false,  true, false,  true,  true,  true,  true,  true, // !"#$%&'
     408             :             false, false,  true,  true, false,  true, false, false, //()*+,-./
     409             :              true,  true,  true,  true,  true,  true,  true,  true, //01234567
     410             :              true,  true, false, false, false, false, false, false, //89:;<=>?
     411             :             false,  true,  true,  true,  true,  true,  true,  true, //@ABCDEFG
     412             :              true,  true,  true,  true,  true,  true,  true,  true, //HIJKLMNO
     413             :              true,  true,  true,  true,  true,  true,  true,  true, //PQRSTUVW
     414             :              true,  true,  true, false, false, false,  true,  true, //XYZ[\]^_
     415             :              true,  true,  true,  true,  true,  true,  true,  true, //`abcdefg
     416             :              true,  true,  true,  true,  true,  true,  true,  true, //hijklmno
     417             :              true,  true,  true,  true,  true,  true,  true,  true, //pqrstuvw
     418             :              true,  true,  true,  true,  true,  true,  true, false  //xyz{|}~
     419             :           };
     420           0 :     return rtl::isAscii(nChar) && aMap[nChar];
     421             : }
     422             : 
     423             : // static
     424           0 : bool INetMIME::isIMAPAtomChar(sal_uInt32 nChar)
     425             : {
     426             :     static const bool aMap[128]
     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, false, false, false, false, false, false, false,
     431             :             false,  true, false,  true,  true, false,  true,  true, // !"#$%&'
     432             :             false, false, false,  true,  true,  true,  true,  true, //()*+,-./
     433             :              true,  true,  true,  true,  true,  true,  true,  true, //01234567
     434             :              true,  true,  true,  true,  true,  true,  true,  true, //89:;<=>?
     435             :              true,  true,  true,  true,  true,  true,  true,  true, //@ABCDEFG
     436             :              true,  true,  true,  true,  true,  true,  true,  true, //HIJKLMNO
     437             :              true,  true,  true,  true,  true,  true,  true,  true, //PQRSTUVW
     438             :              true,  true,  true,  true, false,  true,  true,  true, //XYZ[\]^_
     439             :              true,  true,  true,  true,  true,  true,  true,  true, //`abcdefg
     440             :              true,  true,  true,  true,  true,  true,  true,  true, //hijklmno
     441             :              true,  true,  true,  true,  true,  true,  true,  true, //pqrstuvw
     442             :              true,  true,  true, false,  true,  true,  true, false  //xyz{|}~
     443             :           };
     444           0 :     return rtl::isAscii(nChar) && aMap[nChar];
     445             : }
     446             : 
     447             : // static
     448           0 : sal_uInt32 INetMIME::getHexDigit(int nWeight)
     449             : {
     450             :     DBG_ASSERT(nWeight >= 0 && nWeight < 16,
     451             :                "INetMIME::getHexDigit(): Bad weight");
     452             : 
     453             :     static const sal_Char aDigits[16]
     454             :         = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
     455             :             'D', 'E', 'F' };
     456           0 :     return aDigits[nWeight];
     457             : }
     458             : 
     459             : // static
     460           0 : bool INetMIME::equalIgnoreCase(const sal_Char * pBegin1,
     461             :                                const sal_Char * pEnd1,
     462             :                                const sal_Char * pString2)
     463             : {
     464             :     DBG_ASSERT(pBegin1 && pBegin1 <= pEnd1 && pString2,
     465             :                "INetMIME::equalIgnoreCase(): Bad sequences");
     466             : 
     467           0 :     while (*pString2 != 0)
     468           0 :         if (pBegin1 == pEnd1
     469           0 :             || rtl::toAsciiUpperCase(*pBegin1++) != rtl::toAsciiUpperCase(*pString2++))
     470           0 :             return false;
     471           0 :     return pBegin1 == pEnd1;
     472             : }
     473             : 
     474             : // static
     475           0 : bool INetMIME::equalIgnoreCase(const sal_Unicode * pBegin1,
     476             :                                const sal_Unicode * pEnd1,
     477             :                                const sal_Char * pString2)
     478             : {
     479             :     DBG_ASSERT(pBegin1 && pBegin1 <= pEnd1 && pString2,
     480             :                "INetMIME::equalIgnoreCase(): Bad sequences");
     481             : 
     482           0 :     while (*pString2 != 0)
     483           0 :         if (pBegin1 == pEnd1
     484           0 :             || rtl::toAsciiUpperCase(*pBegin1++) != rtl::toAsciiUpperCase(*pString2++))
     485           0 :             return false;
     486           0 :     return pBegin1 == pEnd1;
     487             : }
     488             : 
     489             : // static
     490           0 : const sal_Unicode * INetMIME::skipLinearWhiteSpace(const sal_Unicode * pBegin,
     491             :                                                    const sal_Unicode * pEnd)
     492             : {
     493             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
     494             :                "INetMIME::skipLinearWhiteSpace(): Bad sequence");
     495             : 
     496           0 :     while (pBegin != pEnd)
     497           0 :         switch (*pBegin)
     498             :         {
     499             :             case '\t':
     500             :             case ' ':
     501           0 :                 ++pBegin;
     502           0 :                 break;
     503             : 
     504             :             case 0x0D: // CR
     505           0 :                 if (startsWithLineFolding(pBegin, pEnd))
     506           0 :                     pBegin += 3;
     507             :                 else
     508           0 :                     return pBegin;
     509           0 :                 break;
     510             : 
     511             :             default:
     512           0 :                 return pBegin;
     513             :         }
     514           0 :     return pBegin;
     515             : }
     516             : 
     517             : // static
     518           0 : const sal_Unicode * INetMIME::skipComment(const sal_Unicode * pBegin,
     519             :                                           const sal_Unicode * pEnd)
     520             : {
     521             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
     522             :                "INetMIME::skipComment(): Bad sequence");
     523             : 
     524           0 :     if (pBegin != pEnd && *pBegin == '(')
     525             :     {
     526           0 :         sal_uInt32 nLevel = 0;
     527           0 :         for (const sal_Unicode * p = pBegin; p != pEnd;)
     528           0 :             switch (*p++)
     529             :             {
     530             :                 case '(':
     531           0 :                     ++nLevel;
     532           0 :                     break;
     533             : 
     534             :                 case ')':
     535           0 :                     if (--nLevel == 0)
     536           0 :                         return p;
     537           0 :                     break;
     538             : 
     539             :                 case '\\':
     540           0 :                     if (p != pEnd)
     541           0 :                         ++p;
     542           0 :                     break;
     543             :             }
     544             :     }
     545           0 :     return pBegin;
     546             : }
     547             : 
     548             : // static
     549           0 : const sal_Unicode * INetMIME::skipLinearWhiteSpaceComment(const sal_Unicode *
     550             :                                                               pBegin,
     551             :                                                           const sal_Unicode *
     552             :                                                               pEnd)
     553             : {
     554             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
     555             :                "INetMIME::skipLinearWhiteSpaceComment(): Bad sequence");
     556             : 
     557           0 :     while (pBegin != pEnd)
     558           0 :         switch (*pBegin)
     559             :         {
     560             :             case '\t':
     561             :             case ' ':
     562           0 :                 ++pBegin;
     563           0 :                 break;
     564             : 
     565             :             case 0x0D: // CR
     566           0 :                 if (startsWithLineFolding(pBegin, pEnd))
     567           0 :                     pBegin += 3;
     568             :                 else
     569           0 :                     return pBegin;
     570           0 :                 break;
     571             : 
     572             :             case '(':
     573             :             {
     574           0 :                 const sal_Unicode * p = skipComment(pBegin, pEnd);
     575           0 :                 if (p == pBegin)
     576           0 :                     return pBegin;
     577           0 :                 pBegin = p;
     578           0 :                 break;
     579             :             }
     580             : 
     581             :             default:
     582           0 :                 return pBegin;
     583             :         }
     584           0 :     return pBegin;
     585             : }
     586             : 
     587             : // static
     588           0 : const sal_Char * INetMIME::skipQuotedString(const sal_Char * pBegin,
     589             :                                             const sal_Char * pEnd)
     590             : {
     591             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
     592             :                "INetMIME::skipQuotedString(): Bad sequence");
     593             : 
     594           0 :     if (pBegin != pEnd && *pBegin == '"')
     595           0 :         for (const sal_Char * p = pBegin + 1; p != pEnd;)
     596           0 :             switch (*p++)
     597             :             {
     598             :                 case 0x0D: // CR
     599           0 :                     if (pEnd - p < 2 || *p++ != 0x0A // LF
     600           0 :                         || !isWhiteSpace(*p++))
     601           0 :                         return pBegin;
     602           0 :                     break;
     603             : 
     604             :                 case '"':
     605           0 :                     return p;
     606             : 
     607             :                 case '\\':
     608           0 :                     if (p != pEnd)
     609           0 :                         ++p;
     610           0 :                     break;
     611             :             }
     612           0 :     return pBegin;
     613             : }
     614             : 
     615             : // static
     616           0 : const sal_Unicode * INetMIME::skipQuotedString(const sal_Unicode * pBegin,
     617             :                                                const sal_Unicode * pEnd)
     618             : {
     619             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
     620             :                "INetMIME::skipQuotedString(): Bad sequence");
     621             : 
     622           0 :     if (pBegin != pEnd && *pBegin == '"')
     623           0 :         for (const sal_Unicode * p = pBegin + 1; p != pEnd;)
     624           0 :             switch (*p++)
     625             :             {
     626             :                 case 0x0D: // CR
     627           0 :                     if (pEnd - p < 2 || *p++ != 0x0A // LF
     628           0 :                         || !isWhiteSpace(*p++))
     629           0 :                         return pBegin;
     630           0 :                     break;
     631             : 
     632             :                 case '"':
     633           0 :                     return p;
     634             : 
     635             :                 case '\\':
     636           0 :                     if (p != pEnd)
     637           0 :                         ++p;
     638           0 :                     break;
     639             :             }
     640           0 :     return pBegin;
     641             : }
     642             : 
     643             : // static
     644           0 : bool INetMIME::scanUnsigned(const sal_Unicode *& rBegin,
     645             :                             const sal_Unicode * pEnd, bool bLeadingZeroes,
     646             :                             sal_uInt32 & rValue)
     647             : {
     648           0 :     sal_uInt64 nTheValue = 0;
     649           0 :     const sal_Unicode * p = rBegin;
     650           0 :     for ( ; p != pEnd; ++p)
     651             :     {
     652           0 :         int nWeight = getWeight(*p);
     653           0 :         if (nWeight < 0)
     654           0 :             break;
     655           0 :         nTheValue = 10 * nTheValue + nWeight;
     656           0 :         if (nTheValue > std::numeric_limits< sal_uInt32 >::max())
     657           0 :             return false;
     658             :     }
     659           0 :     if (nTheValue == 0 && (p == rBegin || (!bLeadingZeroes && p - rBegin != 1)))
     660           0 :         return false;
     661           0 :     rBegin = p;
     662           0 :     rValue = sal_uInt32(nTheValue);
     663           0 :     return true;
     664             : }
     665             : 
     666             : // static
     667           0 : const sal_Unicode * INetMIME::scanQuotedBlock(const sal_Unicode * pBegin,
     668             :                                               const sal_Unicode * pEnd,
     669             :                                               sal_uInt32 nOpening,
     670             :                                               sal_uInt32 nClosing,
     671             :                                               sal_Size & rLength,
     672             :                                               bool & rModify)
     673             : {
     674             :     DBG_ASSERT(pBegin && pBegin <= pEnd,
     675             :                "INetMIME::scanQuotedBlock(): Bad sequence");
     676             : 
     677           0 :     if (pBegin != pEnd && *pBegin == nOpening)
     678             :     {
     679           0 :         ++rLength;
     680           0 :         ++pBegin;
     681           0 :         while (pBegin != pEnd)
     682           0 :             if (*pBegin == nClosing)
     683             :             {
     684           0 :                 ++rLength;
     685           0 :                 return ++pBegin;
     686             :             }
     687             :             else
     688             :             {
     689           0 :                 sal_uInt32 c = *pBegin++;
     690           0 :                 switch (c)
     691             :                 {
     692             :                     case 0x0D: // CR
     693           0 :                         if (pBegin != pEnd && *pBegin == 0x0A) // LF
     694           0 :                             if (pEnd - pBegin >= 2 && isWhiteSpace(pBegin[1]))
     695             :                             {
     696           0 :                                 ++rLength;
     697           0 :                                 rModify = true;
     698           0 :                                 pBegin += 2;
     699             :                             }
     700             :                             else
     701             :                             {
     702           0 :                                 rLength += 3;
     703           0 :                                 rModify = true;
     704           0 :                                 ++pBegin;
     705             :                             }
     706             :                         else
     707           0 :                             ++rLength;
     708           0 :                         break;
     709             : 
     710             :                     case '\\':
     711           0 :                         ++rLength;
     712           0 :                         if (pBegin != pEnd)
     713             :                         {
     714           0 :                             if (startsWithLineBreak(pBegin, pEnd)
     715           0 :                                 && (pEnd - pBegin < 3
     716           0 :                                     || !isWhiteSpace(pBegin[2])))
     717             :                             {
     718           0 :                                 rLength += 3;
     719           0 :                                 rModify = true;
     720           0 :                                 pBegin += 2;
     721             :                             }
     722             :                             else
     723           0 :                                 ++pBegin;
     724             :                         }
     725           0 :                         break;
     726             : 
     727             :                     default:
     728           0 :                         ++rLength;
     729           0 :                         if (!rtl::isAscii(c))
     730           0 :                             rModify = true;
     731           0 :                         break;
     732             :                 }
     733             :             }
     734             :     }
     735           0 :     return pBegin;
     736             : }
     737             : 
     738             : // static
     739           0 : sal_Unicode const * INetMIME::scanParameters(sal_Unicode const * pBegin,
     740             :                                              sal_Unicode const * pEnd,
     741             :                                              INetContentTypeParameterList *
     742             :                                                  pParameters)
     743             : {
     744           0 :     ParameterList aList;
     745           0 :     sal_Unicode const * pParameterBegin = pBegin;
     746           0 :     for (sal_Unicode const * p = pParameterBegin;; pParameterBegin = p)
     747             :     {
     748           0 :         pParameterBegin = skipLinearWhiteSpaceComment(p, pEnd);
     749           0 :         if (pParameterBegin == pEnd || *pParameterBegin != ';')
     750             :             break;
     751           0 :         p = pParameterBegin + 1;
     752             : 
     753             :         sal_Unicode const * pAttributeBegin
     754           0 :             = skipLinearWhiteSpaceComment(p, pEnd);
     755           0 :         p = pAttributeBegin;
     756           0 :         bool bDowncaseAttribute = false;
     757           0 :         while (p != pEnd && isTokenChar(*p) && *p != '*')
     758             :         {
     759           0 :             bDowncaseAttribute = bDowncaseAttribute || rtl::isAsciiUpperCase(*p);
     760           0 :             ++p;
     761             :         }
     762           0 :         if (p == pAttributeBegin)
     763           0 :             break;
     764             :         OString aAttribute = OString(
     765           0 :             pAttributeBegin, p - pAttributeBegin,
     766           0 :             RTL_TEXTENCODING_ASCII_US);
     767           0 :         if (bDowncaseAttribute)
     768           0 :             aAttribute = aAttribute.toAsciiLowerCase();
     769             : 
     770           0 :         sal_uInt32 nSection = 0;
     771           0 :         if (p != pEnd && *p == '*')
     772             :         {
     773           0 :             ++p;
     774           0 :             if (p != pEnd && rtl::isAsciiDigit(*p)
     775           0 :                 && !scanUnsigned(p, pEnd, false, nSection))
     776           0 :                 break;
     777             :         }
     778             : 
     779             :         bool bPresent;
     780           0 :         Parameter ** pPos = aList.find(aAttribute, nSection, bPresent);
     781           0 :         if (bPresent)
     782           0 :             break;
     783             : 
     784           0 :         bool bExtended = false;
     785           0 :         if (p != pEnd && *p == '*')
     786             :         {
     787           0 :             ++p;
     788           0 :             bExtended = true;
     789             :         }
     790             : 
     791           0 :         p = skipLinearWhiteSpaceComment(p, pEnd);
     792             : 
     793           0 :         if (p == pEnd || *p != '=')
     794             :             break;
     795             : 
     796           0 :         p = skipLinearWhiteSpaceComment(p + 1, pEnd);
     797             : 
     798           0 :         OString aCharset;
     799           0 :         OString aLanguage;
     800           0 :         OString aValue;
     801           0 :         if (bExtended)
     802             :         {
     803           0 :             if (nSection == 0)
     804             :             {
     805           0 :                 sal_Unicode const * pCharsetBegin = p;
     806           0 :                 bool bDowncaseCharset = false;
     807           0 :                 while (p != pEnd && isTokenChar(*p) && *p != '\'')
     808             :                 {
     809           0 :                     bDowncaseCharset = bDowncaseCharset || rtl::isAsciiUpperCase(*p);
     810           0 :                     ++p;
     811             :                 }
     812           0 :                 if (p == pCharsetBegin)
     813           0 :                     break;
     814           0 :                 if (pParameters)
     815             :                 {
     816           0 :                     aCharset = OString(
     817             :                         pCharsetBegin,
     818           0 :                         p - pCharsetBegin,
     819           0 :                         RTL_TEXTENCODING_ASCII_US);
     820           0 :                     if (bDowncaseCharset)
     821           0 :                         aCharset = aCharset.toAsciiLowerCase();
     822             :                 }
     823             : 
     824           0 :                 if (p == pEnd || *p != '\'')
     825             :                     break;
     826           0 :                 ++p;
     827             : 
     828           0 :                 sal_Unicode const * pLanguageBegin = p;
     829           0 :                 bool bDowncaseLanguage = false;
     830           0 :                 int nLetters = 0;
     831           0 :                 for (; p != pEnd; ++p)
     832           0 :                     if (rtl::isAsciiAlpha(*p))
     833             :                     {
     834           0 :                         if (++nLetters > 8)
     835           0 :                             break;
     836             :                         bDowncaseLanguage = bDowncaseLanguage
     837           0 :                                             || rtl::isAsciiUpperCase(*p);
     838             :                     }
     839           0 :                     else if (*p == '-')
     840             :                     {
     841           0 :                         if (nLetters == 0)
     842           0 :                             break;
     843           0 :                         nLetters = 0;
     844             :                     }
     845             :                     else
     846           0 :                         break;
     847           0 :                 if (nLetters == 0 || nLetters > 8)
     848             :                     break;
     849           0 :                 if (pParameters)
     850             :                 {
     851           0 :                     aLanguage = OString(
     852             :                         pLanguageBegin,
     853           0 :                         p - pLanguageBegin,
     854           0 :                         RTL_TEXTENCODING_ASCII_US);
     855           0 :                     if (bDowncaseLanguage)
     856           0 :                         aLanguage = aLanguage.toAsciiLowerCase();
     857             :                 }
     858             : 
     859           0 :                 if (p == pEnd || *p != '\'')
     860             :                     break;
     861           0 :                 ++p;
     862             :             }
     863           0 :             if (pParameters)
     864             :             {
     865             :                 INetMIMEStringOutputSink
     866           0 :                     aSink(0, INetMIMEOutputSink::NO_LINE_LENGTH_LIMIT);
     867           0 :                 while (p != pEnd)
     868             :                 {
     869           0 :                     sal_uInt32 nChar = INetMIME::getUTF32Character(p, pEnd);
     870           0 :                     if (rtl::isAscii(nChar) && !isTokenChar(nChar))
     871           0 :                         break;
     872           0 :                     if (nChar == '%' && p + 1 < pEnd)
     873             :                     {
     874           0 :                         int nWeight1 = getHexWeight(p[0]);
     875           0 :                         int nWeight2 = getHexWeight(p[1]);
     876           0 :                         if (nWeight1 >= 0 && nWeight2 >= 0)
     877             :                         {
     878           0 :                             aSink << sal_Char(nWeight1 << 4 | nWeight2);
     879           0 :                             p += 2;
     880           0 :                             continue;
     881             :                         }
     882             :                     }
     883           0 :                     INetMIME::writeUTF8(aSink, nChar);
     884             :                 }
     885           0 :                 aValue = aSink.takeBuffer();
     886             :             }
     887             :             else
     888           0 :                 while (p != pEnd && (isTokenChar(*p) || !rtl::isAscii(*p)))
     889           0 :                     ++p;
     890             :         }
     891           0 :         else if (p != pEnd && *p == '"')
     892           0 :             if (pParameters)
     893             :             {
     894             :                 INetMIMEStringOutputSink
     895           0 :                     aSink(0, INetMIMEOutputSink::NO_LINE_LENGTH_LIMIT);
     896           0 :                 bool bInvalid = false;
     897           0 :                 for (++p;;)
     898             :                 {
     899           0 :                     if (p == pEnd)
     900             :                     {
     901           0 :                         bInvalid = true;
     902           0 :                         break;
     903             :                     }
     904           0 :                     sal_uInt32 nChar = INetMIME::getUTF32Character(p, pEnd);
     905           0 :                     if (nChar == '"')
     906           0 :                         break;
     907           0 :                     else if (nChar == 0x0D) // CR
     908             :                     {
     909           0 :                         if (pEnd - p < 2 || *p++ != 0x0A // LF
     910           0 :                             || !isWhiteSpace(*p))
     911             :                         {
     912           0 :                             bInvalid = true;
     913           0 :                             break;
     914             :                         }
     915           0 :                         nChar = static_cast<unsigned char>(*p++);
     916             :                     }
     917           0 :                     else if (nChar == '\\')
     918             :                     {
     919           0 :                         if (p == pEnd)
     920             :                         {
     921           0 :                             bInvalid = true;
     922           0 :                             break;
     923             :                         }
     924           0 :                         nChar = INetMIME::getUTF32Character(p, pEnd);
     925             :                     }
     926           0 :                     INetMIME::writeUTF8(aSink, nChar);
     927           0 :                 }
     928           0 :                 if (bInvalid)
     929           0 :                     break;
     930           0 :                 aValue = aSink.takeBuffer();
     931             :             }
     932             :             else
     933             :             {
     934           0 :                 sal_Unicode const * pStringEnd = skipQuotedString(p, pEnd);
     935           0 :                 if (p == pStringEnd)
     936           0 :                     break;
     937           0 :                 p = pStringEnd;
     938           0 :             }
     939             :         else
     940             :         {
     941           0 :             sal_Unicode const * pTokenBegin = p;
     942           0 :             while (p != pEnd && (isTokenChar(*p) || !rtl::isAscii(*p)))
     943           0 :                 ++p;
     944           0 :             if (p == pTokenBegin)
     945           0 :                 break;
     946           0 :             if (pParameters)
     947           0 :                 aValue = OString(
     948           0 :                     pTokenBegin, p - pTokenBegin,
     949           0 :                     RTL_TEXTENCODING_UTF8);
     950             :         }
     951             : 
     952             :         *pPos = new Parameter(*pPos, aAttribute, aCharset, aLanguage, aValue,
     953           0 :                               nSection, bExtended);
     954           0 :     }
     955           0 :     return parseParameters(aList, pParameters) ? pParameterBegin : pBegin;
     956             : }
     957             : 
     958             : // static
     959           0 : const sal_Char * INetMIME::getCharsetName(rtl_TextEncoding eEncoding)
     960             : {
     961           0 :     if (rtl_isOctetTextEncoding(eEncoding))
     962             :     {
     963           0 :         char const * p = rtl_getMimeCharsetFromTextEncoding(eEncoding);
     964             :         DBG_ASSERT(p, "INetMIME::getCharsetName(): Unsupported encoding");
     965           0 :         return p;
     966             :     }
     967             :     else
     968           0 :         switch (eEncoding)
     969             :         {
     970             :             case RTL_TEXTENCODING_UCS4:
     971           0 :                 return "ISO-10646-UCS-4";
     972             : 
     973             :             case RTL_TEXTENCODING_UCS2:
     974           0 :                 return "ISO-10646-UCS-2";
     975             : 
     976             :             default:
     977             :                 OSL_FAIL("INetMIME::getCharsetName(): Unsupported encoding");
     978           0 :                 return 0;
     979             :         }
     980             : }
     981             : 
     982             : namespace unnamed_tools_inetmime {
     983             : 
     984             : struct EncodingEntry
     985             : {
     986             :     sal_Char const * m_aName;
     987             :     rtl_TextEncoding m_eEncoding;
     988             : };
     989             : 
     990             : // The source for the following table is <ftp://ftp.iana.org/in-notes/iana/
     991             : // assignments/character-sets> as of Jan, 21 2000 12:46:00, unless  otherwise
     992             : // noted:
     993             : EncodingEntry const aEncodingMap[]
     994             :     = { { "US-ASCII", RTL_TEXTENCODING_ASCII_US },
     995             :         { "ANSI_X3.4-1968", RTL_TEXTENCODING_ASCII_US },
     996             :         { "ISO-IR-6", RTL_TEXTENCODING_ASCII_US },
     997             :         { "ANSI_X3.4-1986", RTL_TEXTENCODING_ASCII_US },
     998             :         { "ISO_646.IRV:1991", RTL_TEXTENCODING_ASCII_US },
     999             :         { "ASCII", RTL_TEXTENCODING_ASCII_US },
    1000             :         { "ISO646-US", RTL_TEXTENCODING_ASCII_US },
    1001             :         { "US", RTL_TEXTENCODING_ASCII_US },
    1002             :         { "IBM367", RTL_TEXTENCODING_ASCII_US },
    1003             :         { "CP367", RTL_TEXTENCODING_ASCII_US },
    1004             :         { "CSASCII", RTL_TEXTENCODING_ASCII_US },
    1005             :         { "ISO-8859-1", RTL_TEXTENCODING_ISO_8859_1 },
    1006             :         { "ISO_8859-1:1987", RTL_TEXTENCODING_ISO_8859_1 },
    1007             :         { "ISO-IR-100", RTL_TEXTENCODING_ISO_8859_1 },
    1008             :         { "ISO_8859-1", RTL_TEXTENCODING_ISO_8859_1 },
    1009             :         { "LATIN1", RTL_TEXTENCODING_ISO_8859_1 },
    1010             :         { "L1", RTL_TEXTENCODING_ISO_8859_1 },
    1011             :         { "IBM819", RTL_TEXTENCODING_ISO_8859_1 },
    1012             :         { "CP819", RTL_TEXTENCODING_ISO_8859_1 },
    1013             :         { "CSISOLATIN1", RTL_TEXTENCODING_ISO_8859_1 },
    1014             :         { "ISO-8859-2", RTL_TEXTENCODING_ISO_8859_2 },
    1015             :         { "ISO_8859-2:1987", RTL_TEXTENCODING_ISO_8859_2 },
    1016             :         { "ISO-IR-101", RTL_TEXTENCODING_ISO_8859_2 },
    1017             :         { "ISO_8859-2", RTL_TEXTENCODING_ISO_8859_2 },
    1018             :         { "LATIN2", RTL_TEXTENCODING_ISO_8859_2 },
    1019             :         { "L2", RTL_TEXTENCODING_ISO_8859_2 },
    1020             :         { "CSISOLATIN2", RTL_TEXTENCODING_ISO_8859_2 },
    1021             :         { "ISO-8859-3", RTL_TEXTENCODING_ISO_8859_3 },
    1022             :         { "ISO_8859-3:1988", RTL_TEXTENCODING_ISO_8859_3 },
    1023             :         { "ISO-IR-109", RTL_TEXTENCODING_ISO_8859_3 },
    1024             :         { "ISO_8859-3", RTL_TEXTENCODING_ISO_8859_3 },
    1025             :         { "LATIN3", RTL_TEXTENCODING_ISO_8859_3 },
    1026             :         { "L3", RTL_TEXTENCODING_ISO_8859_3 },
    1027             :         { "CSISOLATIN3", RTL_TEXTENCODING_ISO_8859_3 },
    1028             :         { "ISO-8859-4", RTL_TEXTENCODING_ISO_8859_4 },
    1029             :         { "ISO_8859-4:1988", RTL_TEXTENCODING_ISO_8859_4 },
    1030             :         { "ISO-IR-110", RTL_TEXTENCODING_ISO_8859_4 },
    1031             :         { "ISO_8859-4", RTL_TEXTENCODING_ISO_8859_4 },
    1032             :         { "LATIN4", RTL_TEXTENCODING_ISO_8859_4 },
    1033             :         { "L4", RTL_TEXTENCODING_ISO_8859_4 },
    1034             :         { "CSISOLATIN4", RTL_TEXTENCODING_ISO_8859_4 },
    1035             :         { "ISO-8859-5", RTL_TEXTENCODING_ISO_8859_5 },
    1036             :         { "ISO_8859-5:1988", RTL_TEXTENCODING_ISO_8859_5 },
    1037             :         { "ISO-IR-144", RTL_TEXTENCODING_ISO_8859_5 },
    1038             :         { "ISO_8859-5", RTL_TEXTENCODING_ISO_8859_5 },
    1039             :         { "CYRILLIC", RTL_TEXTENCODING_ISO_8859_5 },
    1040             :         { "CSISOLATINCYRILLIC", RTL_TEXTENCODING_ISO_8859_5 },
    1041             :         { "ISO-8859-6", RTL_TEXTENCODING_ISO_8859_6 },
    1042             :         { "ISO_8859-6:1987", RTL_TEXTENCODING_ISO_8859_6 },
    1043             :         { "ISO-IR-127", RTL_TEXTENCODING_ISO_8859_6 },
    1044             :         { "ISO_8859-6", RTL_TEXTENCODING_ISO_8859_6 },
    1045             :         { "ECMA-114", RTL_TEXTENCODING_ISO_8859_6 },
    1046             :         { "ASMO-708", RTL_TEXTENCODING_ISO_8859_6 },
    1047             :         { "ARABIC", RTL_TEXTENCODING_ISO_8859_6 },
    1048             :         { "CSISOLATINARABIC", RTL_TEXTENCODING_ISO_8859_6 },
    1049             :         { "ISO-8859-7", RTL_TEXTENCODING_ISO_8859_7 },
    1050             :         { "ISO_8859-7:1987", RTL_TEXTENCODING_ISO_8859_7 },
    1051             :         { "ISO-IR-126", RTL_TEXTENCODING_ISO_8859_7 },
    1052             :         { "ISO_8859-7", RTL_TEXTENCODING_ISO_8859_7 },
    1053             :         { "ELOT_928", RTL_TEXTENCODING_ISO_8859_7 },
    1054             :         { "ECMA-118", RTL_TEXTENCODING_ISO_8859_7 },
    1055             :         { "GREEK", RTL_TEXTENCODING_ISO_8859_7 },
    1056             :         { "GREEK8", RTL_TEXTENCODING_ISO_8859_7 },
    1057             :         { "CSISOLATINGREEK", RTL_TEXTENCODING_ISO_8859_7 },
    1058             :         { "ISO-8859-8", RTL_TEXTENCODING_ISO_8859_8 },
    1059             :         { "ISO_8859-8:1988", RTL_TEXTENCODING_ISO_8859_8 },
    1060             :         { "ISO-IR-138", RTL_TEXTENCODING_ISO_8859_8 },
    1061             :         { "ISO_8859-8", RTL_TEXTENCODING_ISO_8859_8 },
    1062             :         { "HEBREW", RTL_TEXTENCODING_ISO_8859_8 },
    1063             :         { "CSISOLATINHEBREW", RTL_TEXTENCODING_ISO_8859_8 },
    1064             :         { "ISO-8859-9", RTL_TEXTENCODING_ISO_8859_9 },
    1065             :         { "ISO_8859-9:1989", RTL_TEXTENCODING_ISO_8859_9 },
    1066             :         { "ISO-IR-148", RTL_TEXTENCODING_ISO_8859_9 },
    1067             :         { "ISO_8859-9", RTL_TEXTENCODING_ISO_8859_9 },
    1068             :         { "LATIN5", RTL_TEXTENCODING_ISO_8859_9 },
    1069             :         { "L5", RTL_TEXTENCODING_ISO_8859_9 },
    1070             :         { "CSISOLATIN5", RTL_TEXTENCODING_ISO_8859_9 },
    1071             :         { "ISO-8859-14", RTL_TEXTENCODING_ISO_8859_14 }, // RFC 2047
    1072             :         { "ISO_8859-15", RTL_TEXTENCODING_ISO_8859_15 },
    1073             :         { "ISO-8859-15", RTL_TEXTENCODING_ISO_8859_15 }, // RFC 2047
    1074             :         { "MACINTOSH", RTL_TEXTENCODING_APPLE_ROMAN },
    1075             :         { "MAC", RTL_TEXTENCODING_APPLE_ROMAN },
    1076             :         { "CSMACINTOSH", RTL_TEXTENCODING_APPLE_ROMAN },
    1077             :         { "IBM437", RTL_TEXTENCODING_IBM_437 },
    1078             :         { "CP437", RTL_TEXTENCODING_IBM_437 },
    1079             :         { "437", RTL_TEXTENCODING_IBM_437 },
    1080             :         { "CSPC8CODEPAGE437", RTL_TEXTENCODING_IBM_437 },
    1081             :         { "IBM850", RTL_TEXTENCODING_IBM_850 },
    1082             :         { "CP850", RTL_TEXTENCODING_IBM_850 },
    1083             :         { "850", RTL_TEXTENCODING_IBM_850 },
    1084             :         { "CSPC850MULTILINGUAL", RTL_TEXTENCODING_IBM_850 },
    1085             :         { "IBM860", RTL_TEXTENCODING_IBM_860 },
    1086             :         { "CP860", RTL_TEXTENCODING_IBM_860 },
    1087             :         { "860", RTL_TEXTENCODING_IBM_860 },
    1088             :         { "CSIBM860", RTL_TEXTENCODING_IBM_860 },
    1089             :         { "IBM861", RTL_TEXTENCODING_IBM_861 },
    1090             :         { "CP861", RTL_TEXTENCODING_IBM_861 },
    1091             :         { "861", RTL_TEXTENCODING_IBM_861 },
    1092             :         { "CP-IS", RTL_TEXTENCODING_IBM_861 },
    1093             :         { "CSIBM861", RTL_TEXTENCODING_IBM_861 },
    1094             :         { "IBM863", RTL_TEXTENCODING_IBM_863 },
    1095             :         { "CP863", RTL_TEXTENCODING_IBM_863 },
    1096             :         { "863", RTL_TEXTENCODING_IBM_863 },
    1097             :         { "CSIBM863", RTL_TEXTENCODING_IBM_863 },
    1098             :         { "IBM865", RTL_TEXTENCODING_IBM_865 },
    1099             :         { "CP865", RTL_TEXTENCODING_IBM_865 },
    1100             :         { "865", RTL_TEXTENCODING_IBM_865 },
    1101             :         { "CSIBM865", RTL_TEXTENCODING_IBM_865 },
    1102             :         { "IBM775", RTL_TEXTENCODING_IBM_775 },
    1103             :         { "CP775", RTL_TEXTENCODING_IBM_775 },
    1104             :         { "CSPC775BALTIC", RTL_TEXTENCODING_IBM_775 },
    1105             :         { "IBM852", RTL_TEXTENCODING_IBM_852 },
    1106             :         { "CP852", RTL_TEXTENCODING_IBM_852 },
    1107             :         { "852", RTL_TEXTENCODING_IBM_852 },
    1108             :         { "CSPCP852", RTL_TEXTENCODING_IBM_852 },
    1109             :         { "IBM855", RTL_TEXTENCODING_IBM_855 },
    1110             :         { "CP855", RTL_TEXTENCODING_IBM_855 },
    1111             :         { "855", RTL_TEXTENCODING_IBM_855 },
    1112             :         { "CSIBM855", RTL_TEXTENCODING_IBM_855 },
    1113             :         { "IBM857", RTL_TEXTENCODING_IBM_857 },
    1114             :         { "CP857", RTL_TEXTENCODING_IBM_857 },
    1115             :         { "857", RTL_TEXTENCODING_IBM_857 },
    1116             :         { "CSIBM857", RTL_TEXTENCODING_IBM_857 },
    1117             :         { "IBM862", RTL_TEXTENCODING_IBM_862 },
    1118             :         { "CP862", RTL_TEXTENCODING_IBM_862 },
    1119             :         { "862", RTL_TEXTENCODING_IBM_862 },
    1120             :         { "CSPC862LATINHEBREW", RTL_TEXTENCODING_IBM_862 },
    1121             :         { "IBM864", RTL_TEXTENCODING_IBM_864 },
    1122             :         { "CP864", RTL_TEXTENCODING_IBM_864 },
    1123             :         { "CSIBM864", RTL_TEXTENCODING_IBM_864 },
    1124             :         { "IBM866", RTL_TEXTENCODING_IBM_866 },
    1125             :         { "CP866", RTL_TEXTENCODING_IBM_866 },
    1126             :         { "866", RTL_TEXTENCODING_IBM_866 },
    1127             :         { "CSIBM866", RTL_TEXTENCODING_IBM_866 },
    1128             :         { "IBM869", RTL_TEXTENCODING_IBM_869 },
    1129             :         { "CP869", RTL_TEXTENCODING_IBM_869 },
    1130             :         { "869", RTL_TEXTENCODING_IBM_869 },
    1131             :         { "CP-GR", RTL_TEXTENCODING_IBM_869 },
    1132             :         { "CSIBM869", RTL_TEXTENCODING_IBM_869 },
    1133             :         { "WINDOWS-1250", RTL_TEXTENCODING_MS_1250 },
    1134             :         { "WINDOWS-1251", RTL_TEXTENCODING_MS_1251 },
    1135             :         { "WINDOWS-1253", RTL_TEXTENCODING_MS_1253 },
    1136             :         { "WINDOWS-1254", RTL_TEXTENCODING_MS_1254 },
    1137             :         { "WINDOWS-1255", RTL_TEXTENCODING_MS_1255 },
    1138             :         { "WINDOWS-1256", RTL_TEXTENCODING_MS_1256 },
    1139             :         { "WINDOWS-1257", RTL_TEXTENCODING_MS_1257 },
    1140             :         { "WINDOWS-1258", RTL_TEXTENCODING_MS_1258 },
    1141             :         { "SHIFT_JIS", RTL_TEXTENCODING_SHIFT_JIS },
    1142             :         { "MS_KANJI", RTL_TEXTENCODING_SHIFT_JIS },
    1143             :         { "CSSHIFTJIS", RTL_TEXTENCODING_SHIFT_JIS },
    1144             :         { "GB2312", RTL_TEXTENCODING_GB_2312 },
    1145             :         { "CSGB2312", RTL_TEXTENCODING_GB_2312 },
    1146             :         { "BIG5", RTL_TEXTENCODING_BIG5 },
    1147             :         { "CSBIG5", RTL_TEXTENCODING_BIG5 },
    1148             :         { "EUC-JP", RTL_TEXTENCODING_EUC_JP },
    1149             :         { "EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE",
    1150             :           RTL_TEXTENCODING_EUC_JP },
    1151             :         { "CSEUCPKDFMTJAPANESE", RTL_TEXTENCODING_EUC_JP },
    1152             :         { "ISO-2022-JP", RTL_TEXTENCODING_ISO_2022_JP },
    1153             :         { "CSISO2022JP", RTL_TEXTENCODING_ISO_2022_JP },
    1154             :         { "ISO-2022-CN", RTL_TEXTENCODING_ISO_2022_CN },
    1155             :         { "KOI8-R", RTL_TEXTENCODING_KOI8_R },
    1156             :         { "CSKOI8R", RTL_TEXTENCODING_KOI8_R },
    1157             :         { "UTF-7", RTL_TEXTENCODING_UTF7 },
    1158             :         { "UTF-8", RTL_TEXTENCODING_UTF8 },
    1159             :         { "ISO-8859-10", RTL_TEXTENCODING_ISO_8859_10 }, // RFC 2047
    1160             :         { "ISO-8859-13", RTL_TEXTENCODING_ISO_8859_13 }, // RFC 2047
    1161             :         { "EUC-KR", RTL_TEXTENCODING_EUC_KR },
    1162             :         { "CSEUCKR", RTL_TEXTENCODING_EUC_KR },
    1163             :         { "ISO-2022-KR", RTL_TEXTENCODING_ISO_2022_KR },
    1164             :         { "CSISO2022KR", RTL_TEXTENCODING_ISO_2022_KR },
    1165             :         { "ISO-10646-UCS-4", RTL_TEXTENCODING_UCS4 },
    1166             :         { "CSUCS4", RTL_TEXTENCODING_UCS4 },
    1167             :         { "ISO-10646-UCS-2", RTL_TEXTENCODING_UCS2 },
    1168             :         { "CSUNICODE", RTL_TEXTENCODING_UCS2 } };
    1169             : 
    1170             : template< typename T >
    1171           0 : inline rtl_TextEncoding getCharsetEncoding_Impl(T const * pBegin,
    1172             :                                                 T const * pEnd)
    1173             : {
    1174           0 :     for (sal_Size i = 0; i < sizeof aEncodingMap / sizeof (EncodingEntry);
    1175             :          ++i)
    1176           0 :         if (INetMIME::equalIgnoreCase(pBegin, pEnd, aEncodingMap[i].m_aName))
    1177           0 :             return aEncodingMap[i].m_eEncoding;
    1178           0 :     return RTL_TEXTENCODING_DONTKNOW;
    1179             : }
    1180             : 
    1181             : }
    1182             : 
    1183             : // static
    1184           0 : rtl_TextEncoding INetMIME::getCharsetEncoding(sal_Char const * pBegin,
    1185             :                                               sal_Char const * pEnd)
    1186             : {
    1187           0 :     return getCharsetEncoding_Impl(pBegin, pEnd);
    1188             : }
    1189             : 
    1190             : // static
    1191             : INetMIMECharsetList_Impl *
    1192           0 : INetMIME::createPreferredCharsetList(rtl_TextEncoding eEncoding)
    1193             : {
    1194             :     static const sal_uInt32 aUSASCIIRanges[] = { 0, 0x7F, sal_uInt32(-1) };
    1195             : 
    1196             :     static const sal_uInt32 aISO88591Ranges[] = { 0, 0xFF, sal_uInt32(-1) };
    1197             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-1.TXT> version
    1198             :         // 1.0 of 1999 July 27
    1199             : 
    1200             :     static const sal_uInt32 aISO88592Ranges[]
    1201             :         = { 0, 0xA0, 0xA4, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xB0, 0xB0,
    1202             :             0xB4, 0xB4, 0xB8, 0xB8, 0xC1, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7,
    1203             :             0xC9, 0xC9, 0xCB, 0xCB, 0xCD, 0xCE, 0xD3, 0xD4, 0xD6, 0xD7,
    1204             :             0xDA, 0xDA, 0xDC, 0xDD, 0xDF, 0xDF, 0xE1, 0xE2, 0xE4, 0xE4,
    1205             :             0xE7, 0xE7, 0xE9, 0xE9, 0xEB, 0xEB, 0xED, 0xEE, 0xF3, 0xF4,
    1206             :             0xF6, 0xF7, 0xFA, 0xFA, 0xFC, 0xFD, 0x102, 0x107, 0x10C, 0x111,
    1207             :             0x118, 0x11B, 0x139, 0x13A, 0x13D, 0x13E, 0x141, 0x144,
    1208             :             0x147, 0x148, 0x150, 0x151, 0x154, 0x155, 0x158, 0x15B,
    1209             :             0x15E, 0x165, 0x16E, 0x171, 0x179, 0x17E, 0x2C7, 0x2C7,
    1210             :             0x2D8, 0x2D9, 0x2DB, 0x2DB, 0x2DD, 0x2DD, sal_uInt32(-1) };
    1211             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-2.TXT> version
    1212             :         // 1.0 of 1999 July 27
    1213             : 
    1214             :     static const sal_uInt32 aISO88593Ranges[]
    1215             :         = { 0, 0xA0, 0xA3, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xB0, 0xB0,
    1216             :             0xB2, 0xB5, 0xB7, 0xB8, 0xBD, 0xBD, 0xC0, 0xC2, 0xC4, 0xC4,
    1217             :             0xC7, 0xCF, 0xD1, 0xD4, 0xD6, 0xD7, 0xD9, 0xDC, 0xDF, 0xE2,
    1218             :             0xE4, 0xE4, 0xE7, 0xEF, 0xF1, 0xF4, 0xF6, 0xF7, 0xF9, 0xFC,
    1219             :             0x108, 0x10B, 0x11C, 0x121, 0x124, 0x127, 0x130, 0x131,
    1220             :             0x134, 0x135, 0x15C, 0x15F, 0x16C, 0x16D, 0x17B, 0x17C,
    1221             :             0x2D8, 0x2D9, sal_uInt32(-1) };
    1222             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-3.TXT> version
    1223             :         // 1.0 of 1999 July 27
    1224             : 
    1225             :     static const sal_uInt32 aISO88594Ranges[]
    1226             :         = { 0, 0xA0, 0xA4, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xAF, 0xB0,
    1227             :             0xB4, 0xB4, 0xB8, 0xB8, 0xC1, 0xC6, 0xC9, 0xC9, 0xCB, 0xCB,
    1228             :             0xCD, 0xCE, 0xD4, 0xD8, 0xDA, 0xDC, 0xDF, 0xDF, 0xE1, 0xE6,
    1229             :             0xE9, 0xE9, 0xEB, 0xEB, 0xED, 0xEE, 0xF4, 0xF8, 0xFA, 0xFC,
    1230             :             0x100, 0x101, 0x104, 0x105, 0x10C, 0x10D, 0x110, 0x113,
    1231             :             0x116, 0x119, 0x122, 0x123, 0x128, 0x12B, 0x12E, 0x12F,
    1232             :             0x136, 0x138, 0x13B, 0x13C, 0x145, 0x146, 0x14A, 0x14D,
    1233             :             0x156, 0x157, 0x160, 0x161, 0x166, 0x16B, 0x172, 0x173,
    1234             :             0x17D, 0x17E, 0x2C7, 0x2C7, 0x2D9, 0x2D9, 0x2DB, 0x2DB,
    1235             :             sal_uInt32(-1) };
    1236             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-4.TXT> version
    1237             :         // 1.0 of 1999 July 27
    1238             : 
    1239             :     static const sal_uInt32 aISO88595Ranges[]
    1240             :         = { 0, 0xA0, 0xA7, 0xA7, 0xAD, 0xAD, 0x401, 0x40C, 0x40E, 0x44F,
    1241             :             0x451, 0x45C, 0x45E, 0x45F, 0x2116, 0x2116, sal_uInt32(-1) };
    1242             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-5.TXT> version
    1243             :         // 1.0 of 1999 July 27
    1244             : 
    1245             :     static const sal_uInt32 aISO88596Ranges[]
    1246             :         = { 0, 0xA0, 0xA4, 0xA4, 0xAD, 0xAD, 0x60C, 0x60C, 0x61B, 0x61B,
    1247             :             0x61F, 0x61F, 0x621, 0x63A, 0x640, 0x652, sal_uInt32(-1) };
    1248             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-6.TXT> version
    1249             :         // 1.0 of 1999 July 27
    1250             : 
    1251             :     static const sal_uInt32 aISO88597Ranges[]
    1252             :         = { 0, 0xA0, 0xA3, 0xA3, 0xA6, 0xA9, 0xAB, 0xAD, 0xB0, 0xB3,
    1253             :             0xB7, 0xB7, 0xBB, 0xBB, 0xBD, 0xBD, 0x384, 0x386, 0x388, 0x38A,
    1254             :             0x38C, 0x38C, 0x38E, 0x3A1, 0x3A3, 0x3CE, 0x2015, 0x2015,
    1255             :             0x2018, 0x2019, sal_uInt32(-1) };
    1256             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-7.TXT> version
    1257             :         // 1.0 of 1999 July 27
    1258             : 
    1259             :     static const sal_uInt32 aISO88598Ranges[]
    1260             :         = { 0, 0xA0, 0xA2, 0xA9, 0xAB, 0xB9, 0xBB, 0xBE, 0xD7, 0xD7,
    1261             :             0xF7, 0xF7, 0x5D0, 0x5EA, 0x200E, 0x200F, 0x2017, 0x2017,
    1262             :             sal_uInt32(-1) };
    1263             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-8.TXT> version
    1264             :         // 1.1 of 2000-Jan-03
    1265             : 
    1266             :     static const sal_uInt32 aISO88599Ranges[]
    1267             :         = { 0, 0xCF, 0xD1, 0xDC, 0xDF, 0xEF, 0xF1, 0xFC, 0xFF, 0xFF,
    1268             :             0x11E, 0x11F, 0x130, 0x131, 0x15E, 0x15F, sal_uInt32(-1) };
    1269             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-9.TXT> version
    1270             :         // 1.0 of 1999 July 27
    1271             : 
    1272             :     static const sal_uInt32 aISO885910Ranges[]
    1273             :         = { 0, 0xA0, 0xA7, 0xA7, 0xAD, 0xAD, 0xB0, 0xB0, 0xB7, 0xB7,
    1274             :             0xC1, 0xC6, 0xC9, 0xC9, 0xCB, 0xCB, 0xCD, 0xD0, 0xD3, 0xD6,
    1275             :             0xD8, 0xD8, 0xDA, 0xDF, 0xE1, 0xE6, 0xE9, 0xE9, 0xEB, 0xEB,
    1276             :             0xED, 0xF0, 0xF3, 0xF6, 0xF8, 0xF8, 0xFA, 0xFE, 0x100, 0x101,
    1277             :             0x104, 0x105, 0x10C, 0x10D, 0x110, 0x113, 0x116, 0x119,
    1278             :             0x122, 0x123, 0x128, 0x12B, 0x12E, 0x12F, 0x136, 0x138,
    1279             :             0x13B, 0x13C, 0x145, 0x146, 0x14A, 0x14D, 0x160, 0x161,
    1280             :             0x166, 0x16B, 0x172, 0x173, 0x17D, 0x17E, 0x2015, 0x2015,
    1281             :             sal_uInt32(-1) };
    1282             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-10.TXT> version
    1283             :         // 1.1 of 1999 October 11
    1284             : 
    1285             :     static const sal_uInt32 aISO885913Ranges[]
    1286             :         = { 0, 0xA0, 0xA2, 0xA4, 0xA6, 0xA7, 0xA9, 0xA9, 0xAB, 0xAE,
    1287             :             0xB0, 0xB3, 0xB5, 0xB7, 0xB9, 0xB9, 0xBB, 0xBE, 0xC4, 0xC6,
    1288             :             0xC9, 0xC9, 0xD3, 0xD3, 0xD5, 0xD8, 0xDC, 0xDC, 0xDF, 0xDF,
    1289             :             0xE4, 0xE6, 0xE9, 0xE9, 0xF3, 0xF3, 0xF5, 0xF8, 0xFC, 0xFC,
    1290             :             0x100, 0x101, 0x104, 0x107, 0x10C, 0x10D, 0x112, 0x113,
    1291             :             0x116, 0x119, 0x122, 0x123, 0x12A, 0x12B, 0x12E, 0x12F,
    1292             :             0x136, 0x137, 0x13B, 0x13C, 0x141, 0x146, 0x14C, 0x14D,
    1293             :             0x156, 0x157, 0x15A, 0x15B, 0x160, 0x161, 0x16A, 0x16B,
    1294             :             0x172, 0x173, 0x179, 0x17E, 0x2019, 0x2019, 0x201C, 0x201E,
    1295             :             sal_uInt32(-1) };
    1296             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-13.TXT> version
    1297             :         // 1.0 of 1999 July 27
    1298             : 
    1299             :     static const sal_uInt32 aISO885914Ranges[]
    1300             :         = { 0, 0xA0, 0xA3, 0xA3, 0xA7, 0xA7, 0xA9, 0xA9, 0xAD, 0xAE,
    1301             :             0xB6, 0xB6, 0xC0, 0xCF, 0xD1, 0xD6, 0xD8, 0xDD, 0xDF, 0xEF,
    1302             :             0xF1, 0xF6, 0xF8, 0xFD, 0xFF, 0xFF, 0x10A, 0x10B, 0x120, 0x121,
    1303             :             0x174, 0x178, 0x1E02, 0x1E03, 0x1E0A, 0x1E0B, 0x1E1E, 0x1E1F,
    1304             :             0x1E40, 0x1E41, 0x1E56, 0x1E57, 0x1E60, 0x1E61, 0x1E6A, 0x1E6B,
    1305             :             0x1E80, 0x1E85, 0x1EF2, 0x1EF3, sal_uInt32(-1) };
    1306             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-14.TXT> version
    1307             :         // 1.0 of 1999 July 27
    1308             : 
    1309             :     static const sal_uInt32 aISO885915Ranges[]
    1310             :         = { 0, 0xA3, 0xA5, 0xA5, 0xA7, 0xA7, 0xA9, 0xB3, 0xB5, 0xB7,
    1311             :             0xB9, 0xBB, 0xBF, 0xFF, 0x152, 0x153, 0x160, 0x161, 0x178, 0x178,
    1312             :             0x17D, 0x17E, 0x20AC, 0x20AC, sal_uInt32(-1) };
    1313             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-15.TXT> version
    1314             :         // 1.0 of 1999 July 27
    1315             : 
    1316             :     static const sal_uInt32 aKOI8RRanges[]
    1317             :         = { 0, 0x7F, 0xA0, 0xA0, 0xA9, 0xA9, 0xB0, 0xB0, 0xB2, 0xB2,
    1318             :             0xB7, 0xB7, 0xF7, 0xF7, 0x401, 0x401, 0x410, 0x44F, 0x451, 0x451,
    1319             :             0x2219, 0x221A, 0x2248, 0x2248, 0x2264, 0x2265, 0x2320, 0x2321,
    1320             :             0x2500, 0x2500, 0x2502, 0x2502, 0x250C, 0x250C, 0x2510, 0x2510,
    1321             :             0x2514, 0x2514, 0x2518, 0x2518, 0x251C, 0x251C, 0x2524, 0x2524,
    1322             :             0x252C, 0x252C, 0x2534, 0x2534, 0x253C, 0x253C, 0x2550, 0x256C,
    1323             :             0x2580, 0x2580, 0x2584, 0x2584, 0x2588, 0x2588, 0x258C, 0x258C,
    1324             :             0x2590, 0x2593, 0x25A0, 0x25A0, sal_uInt32(-1) };
    1325             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MISC/KOI8-R.TXT>
    1326             :         // version 1.0 of 18 August 1999
    1327             : 
    1328             : #if defined WNT
    1329             :     static const sal_uInt32 aWindows1252Ranges[]
    1330             :         = { 0, 0x7F, 0xA0, 0xFF, 0x152, 0x153, 0x160, 0x161, 0x178, 0x178,
    1331             :             0x17D, 0x17E, 0x192, 0x192, 0x2C6, 0x2C6, 0x2DC, 0x2DC,
    1332             :             0x2013, 0x2014, 0x2018, 0x201A, 0x201C, 0x201E, 0x2020, 0x2022,
    1333             :             0x2026, 0x2026, 0x2030, 0x2030, 0x2039, 0x203A, 0x20AC, 0x20AC,
    1334             :             0x2122, 0x2122, sal_uInt32(-1) };
    1335             :         // <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/
    1336             :         // CP1252.TXT> version 2.01 of 04/15/98
    1337             : #endif // WNT
    1338             : 
    1339           0 :     INetMIMECharsetList_Impl * pList = new INetMIMECharsetList_Impl;
    1340           0 :     switch (eEncoding)
    1341             :     {
    1342             :         case RTL_TEXTENCODING_MS_1252:
    1343             : #if defined WNT
    1344             :             pList->prepend(Charset(RTL_TEXTENCODING_MS_1252,
    1345             :                                    aWindows1252Ranges));
    1346             : #endif // WNT
    1347             :         case RTL_TEXTENCODING_ISO_8859_1:
    1348             :         case RTL_TEXTENCODING_UTF7:
    1349             :         case RTL_TEXTENCODING_UTF8:
    1350           0 :             break;
    1351             : 
    1352             :         case RTL_TEXTENCODING_ISO_8859_2:
    1353             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_2,
    1354           0 :                                    aISO88592Ranges));
    1355           0 :             break;
    1356             : 
    1357             :         case RTL_TEXTENCODING_ISO_8859_3:
    1358             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_3,
    1359           0 :                                    aISO88593Ranges));
    1360           0 :             break;
    1361             : 
    1362             :         case RTL_TEXTENCODING_ISO_8859_4:
    1363             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_4,
    1364           0 :                                    aISO88594Ranges));
    1365           0 :             break;
    1366             : 
    1367             :         case RTL_TEXTENCODING_ISO_8859_5:
    1368             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5,
    1369           0 :                                    aISO88595Ranges));
    1370           0 :             break;
    1371             : 
    1372             :         case RTL_TEXTENCODING_ISO_8859_6:
    1373             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_6,
    1374           0 :                                    aISO88596Ranges));
    1375           0 :             break;
    1376             : 
    1377             :         case RTL_TEXTENCODING_ISO_8859_7:
    1378             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_7,
    1379           0 :                                    aISO88597Ranges));
    1380           0 :             break;
    1381             : 
    1382             :         case RTL_TEXTENCODING_ISO_8859_8:
    1383             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_8,
    1384           0 :                                    aISO88598Ranges));
    1385           0 :             break;
    1386             : 
    1387             :         case RTL_TEXTENCODING_ISO_8859_9:
    1388             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_9,
    1389           0 :                                    aISO88599Ranges));
    1390           0 :             break;
    1391             : 
    1392             :         case RTL_TEXTENCODING_ISO_8859_10:
    1393             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_10,
    1394           0 :                                    aISO885910Ranges));
    1395           0 :             break;
    1396             : 
    1397             :         case RTL_TEXTENCODING_ISO_8859_13:
    1398             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_13,
    1399           0 :                                    aISO885913Ranges));
    1400           0 :             break;
    1401             : 
    1402             :         case RTL_TEXTENCODING_ISO_8859_14:
    1403             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_14,
    1404           0 :                                    aISO885914Ranges));
    1405           0 :             break;
    1406             : 
    1407             :         case RTL_TEXTENCODING_ISO_8859_15:
    1408             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_15,
    1409           0 :                                    aISO885915Ranges));
    1410           0 :             break;
    1411             : 
    1412             :         case RTL_TEXTENCODING_MS_1250:
    1413             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_2,
    1414           0 :                                    aISO88592Ranges));
    1415           0 :             break;
    1416             : 
    1417             :         case RTL_TEXTENCODING_MS_1251:
    1418             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5,
    1419           0 :                                    aISO88595Ranges));
    1420           0 :             break;
    1421             : 
    1422             :         case RTL_TEXTENCODING_MS_1253:
    1423             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_7,
    1424           0 :                                    aISO88597Ranges));
    1425           0 :             break;
    1426             : 
    1427             :         case RTL_TEXTENCODING_MS_1254:
    1428             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_9,
    1429           0 :                                    aISO88599Ranges));
    1430           0 :             break;
    1431             : 
    1432             :         case RTL_TEXTENCODING_MS_1255:
    1433             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_8,
    1434           0 :                                    aISO88598Ranges));
    1435           0 :             break;
    1436             : 
    1437             :         case RTL_TEXTENCODING_MS_1256:
    1438             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_6,
    1439           0 :                                    aISO88596Ranges));
    1440           0 :             break;
    1441             : 
    1442             :         case RTL_TEXTENCODING_MS_1257:
    1443             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_4,
    1444           0 :                                    aISO88594Ranges));
    1445           0 :             break;
    1446             : 
    1447             :         case RTL_TEXTENCODING_KOI8_R:
    1448             :             pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5,
    1449           0 :                                    aISO88595Ranges));
    1450           0 :             pList->prepend(Charset(RTL_TEXTENCODING_KOI8_R, aKOI8RRanges));
    1451           0 :             break;
    1452             : 
    1453             :         default: //@@@ more cases are missing!
    1454             :             OSL_FAIL("INetMIME::createPreferredCharsetList():"
    1455             :                           " Unsupported encoding");
    1456           0 :             break;
    1457             :     }
    1458           0 :     pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_1, aISO88591Ranges));
    1459           0 :     pList->prepend(Charset(RTL_TEXTENCODING_ASCII_US, aUSASCIIRanges));
    1460           0 :     return pList;
    1461             : }
    1462             : 
    1463             : // static
    1464           0 : sal_Unicode * INetMIME::convertToUnicode(const sal_Char * pBegin,
    1465             :                                          const sal_Char * pEnd,
    1466             :                                          rtl_TextEncoding eEncoding,
    1467             :                                          sal_Size & rSize)
    1468             : {
    1469           0 :     if (eEncoding == RTL_TEXTENCODING_DONTKNOW)
    1470           0 :         return 0;
    1471             :     rtl_TextToUnicodeConverter hConverter
    1472           0 :         = rtl_createTextToUnicodeConverter(eEncoding);
    1473             :     rtl_TextToUnicodeContext hContext
    1474           0 :         = rtl_createTextToUnicodeContext(hConverter);
    1475             :     sal_Unicode * pBuffer;
    1476             :     sal_uInt32 nInfo;
    1477           0 :     for (sal_Size nBufferSize = pEnd - pBegin;;
    1478           0 :          nBufferSize += nBufferSize / 3 + 1)
    1479             :     {
    1480           0 :         pBuffer = new sal_Unicode[nBufferSize];
    1481             :         sal_Size nSrcCvtBytes;
    1482             :         rSize = rtl_convertTextToUnicode(
    1483           0 :                     hConverter, hContext, pBegin, pEnd - pBegin, pBuffer,
    1484             :                     nBufferSize,
    1485             :                     RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
    1486             :                         | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
    1487             :                         | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
    1488           0 :                     &nInfo, &nSrcCvtBytes);
    1489           0 :         if (nInfo != RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL)
    1490           0 :             break;
    1491           0 :         delete[] pBuffer;
    1492           0 :         rtl_resetTextToUnicodeContext(hConverter, hContext);
    1493           0 :     }
    1494           0 :     rtl_destroyTextToUnicodeContext(hConverter, hContext);
    1495           0 :     rtl_destroyTextToUnicodeConverter(hConverter);
    1496           0 :     if (nInfo != 0)
    1497             :     {
    1498           0 :         delete[] pBuffer;
    1499           0 :         pBuffer = 0;
    1500             :     }
    1501           0 :     return pBuffer;
    1502             : }
    1503             : 
    1504             : // static
    1505           0 : sal_Char * INetMIME::convertFromUnicode(const sal_Unicode * pBegin,
    1506             :                                         const sal_Unicode * pEnd,
    1507             :                                         rtl_TextEncoding eEncoding,
    1508             :                                         sal_Size & rSize)
    1509             : {
    1510           0 :     if (eEncoding == RTL_TEXTENCODING_DONTKNOW)
    1511           0 :         return 0;
    1512             :     rtl_UnicodeToTextConverter hConverter
    1513           0 :         = rtl_createUnicodeToTextConverter(eEncoding);
    1514             :     rtl_UnicodeToTextContext hContext
    1515           0 :         = rtl_createUnicodeToTextContext(hConverter);
    1516             :     sal_Char * pBuffer;
    1517             :     sal_uInt32 nInfo;
    1518           0 :     for (sal_Size nBufferSize = pEnd - pBegin;;
    1519           0 :          nBufferSize += nBufferSize / 3 + 1)
    1520             :     {
    1521           0 :         pBuffer = new sal_Char[nBufferSize];
    1522             :         sal_Size nSrcCvtBytes;
    1523             :         rSize = rtl_convertUnicodeToText(
    1524           0 :                     hConverter, hContext, pBegin, pEnd - pBegin, pBuffer,
    1525             :                     nBufferSize,
    1526             :                     RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
    1527             :                         | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
    1528             :                         | RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE
    1529             :                         | RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACESTR,
    1530           0 :                     &nInfo, &nSrcCvtBytes);
    1531           0 :         if (nInfo != RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL)
    1532           0 :             break;
    1533           0 :         delete[] pBuffer;
    1534           0 :         rtl_resetUnicodeToTextContext(hConverter, hContext);
    1535           0 :     }
    1536           0 :     rtl_destroyUnicodeToTextContext(hConverter, hContext);
    1537           0 :     rtl_destroyUnicodeToTextConverter(hConverter);
    1538           0 :     if (nInfo != 0)
    1539             :     {
    1540           0 :         delete[] pBuffer;
    1541           0 :         pBuffer = 0;
    1542             :     }
    1543           0 :     return pBuffer;
    1544             : }
    1545             : 
    1546             : // static
    1547           0 : void INetMIME::writeUTF8(INetMIMEOutputSink & rSink, sal_uInt32 nChar)
    1548             : {
    1549             :     // See RFC 2279 for a discussion of UTF-8.
    1550             :     DBG_ASSERT(nChar < 0x80000000, "INetMIME::writeUTF8(): Bad char");
    1551             : 
    1552           0 :     if (nChar < 0x80)
    1553           0 :         rSink << sal_Char(nChar);
    1554           0 :     else if (nChar < 0x800)
    1555           0 :         rSink << sal_Char(nChar >> 6 | 0xC0)
    1556           0 :               << sal_Char((nChar & 0x3F) | 0x80);
    1557           0 :     else if (nChar < 0x10000)
    1558           0 :         rSink << sal_Char(nChar >> 12 | 0xE0)
    1559           0 :               << sal_Char((nChar >> 6 & 0x3F) | 0x80)
    1560           0 :               << sal_Char((nChar & 0x3F) | 0x80);
    1561           0 :     else if (nChar < 0x200000)
    1562           0 :         rSink << sal_Char(nChar >> 18 | 0xF0)
    1563           0 :               << sal_Char((nChar >> 12 & 0x3F) | 0x80)
    1564           0 :               << sal_Char((nChar >> 6 & 0x3F) | 0x80)
    1565           0 :               << sal_Char((nChar & 0x3F) | 0x80);
    1566           0 :     else if (nChar < 0x4000000)
    1567           0 :         rSink << sal_Char(nChar >> 24 | 0xF8)
    1568           0 :               << sal_Char((nChar >> 18 & 0x3F) | 0x80)
    1569           0 :               << sal_Char((nChar >> 12 & 0x3F) | 0x80)
    1570           0 :               << sal_Char((nChar >> 6 & 0x3F) | 0x80)
    1571           0 :               << sal_Char((nChar & 0x3F) | 0x80);
    1572             :     else
    1573           0 :         rSink << sal_Char(nChar >> 30 | 0xFC)
    1574           0 :               << sal_Char((nChar >> 24 & 0x3F) | 0x80)
    1575           0 :               << sal_Char((nChar >> 18 & 0x3F) | 0x80)
    1576           0 :               << sal_Char((nChar >> 12 & 0x3F) | 0x80)
    1577           0 :               << sal_Char((nChar >> 6 & 0x3F) | 0x80)
    1578           0 :               << sal_Char((nChar & 0x3F) | 0x80);
    1579           0 : }
    1580             : 
    1581             : // static
    1582           0 : void INetMIME::writeHeaderFieldBody(INetMIMEOutputSink & rSink,
    1583             :                                     HeaderFieldType eType,
    1584             :                                     const OUString& rBody,
    1585             :                                     rtl_TextEncoding ePreferredEncoding,
    1586             :                                     bool bInitialSpace)
    1587             : {
    1588           0 :     if (eType == HEADER_FIELD_TEXT)
    1589             :     {
    1590             :         INetMIMEEncodedWordOutputSink
    1591             :             aOutput(rSink, INetMIMEEncodedWordOutputSink::CONTEXT_TEXT,
    1592             :                     bInitialSpace ?
    1593             :                         INetMIMEEncodedWordOutputSink::SPACE_ALWAYS :
    1594             :                         INetMIMEEncodedWordOutputSink::SPACE_NO,
    1595           0 :                     ePreferredEncoding);
    1596           0 :         aOutput.write(rBody.getStr(), rBody.getStr() + rBody.getLength());
    1597           0 :         aOutput.flush();
    1598             :     }
    1599             :     else
    1600             :     {
    1601             :         enum Brackets { BRACKETS_OUTSIDE, BRACKETS_OPENING, BRACKETS_INSIDE };
    1602           0 :         Brackets eBrackets = BRACKETS_OUTSIDE;
    1603             : 
    1604           0 :         const sal_Unicode * pBodyPtr = rBody.getStr();
    1605           0 :         const sal_Unicode * pBodyEnd = pBodyPtr + rBody.getLength();
    1606           0 :         while (pBodyPtr != pBodyEnd)
    1607           0 :             switch (*pBodyPtr)
    1608             :             {
    1609             :                 case '\t':
    1610             :                 case ' ':
    1611             :                     // A WSP adds to accumulated space:
    1612           0 :                     bInitialSpace = true;
    1613           0 :                     ++pBodyPtr;
    1614           0 :                     break;
    1615             : 
    1616             :                 case '(':
    1617             :                 {
    1618             :                     // Write a pending '<' if necessary:
    1619           0 :                     if (eBrackets == BRACKETS_OPENING)
    1620             :                     {
    1621           0 :                         if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1622           0 :                                 >= rSink.getLineLengthLimit())
    1623           0 :                             rSink << INetMIMEOutputSink::endl << ' ';
    1624           0 :                         else if (bInitialSpace)
    1625           0 :                             rSink << ' ';
    1626           0 :                         rSink << '<';
    1627           0 :                         bInitialSpace = false;
    1628           0 :                         eBrackets = BRACKETS_INSIDE;
    1629             :                     }
    1630             : 
    1631             :                     // Write the comment, introducing encoded-words where
    1632             :                     // necessary:
    1633           0 :                     int nLevel = 0;
    1634             :                     INetMIMEEncodedWordOutputSink
    1635             :                         aOutput(
    1636             :                             rSink,
    1637             :                             INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT,
    1638             :                             INetMIMEEncodedWordOutputSink::SPACE_NO,
    1639           0 :                             ePreferredEncoding);
    1640           0 :                     while (pBodyPtr != pBodyEnd)
    1641           0 :                         switch (*pBodyPtr)
    1642             :                         {
    1643             :                             case '(':
    1644           0 :                                 aOutput.flush();
    1645           0 :                                 if (rSink.getColumn()
    1646           0 :                                             + (bInitialSpace ? 1 : 0)
    1647           0 :                                         >= rSink.getLineLengthLimit())
    1648           0 :                                     rSink << INetMIMEOutputSink::endl << ' ';
    1649           0 :                                 else if (bInitialSpace)
    1650           0 :                                     rSink << ' ';
    1651           0 :                                 rSink << '(';
    1652           0 :                                 bInitialSpace = false;
    1653           0 :                                 ++nLevel;
    1654           0 :                                 ++pBodyPtr;
    1655           0 :                                 break;
    1656             : 
    1657             :                             case ')':
    1658           0 :                                 aOutput.flush();
    1659           0 :                                 if (rSink.getColumn()
    1660           0 :                                         >= rSink.getLineLengthLimit())
    1661           0 :                                     rSink << INetMIMEOutputSink::endl << ' ';
    1662           0 :                                 rSink << ')';
    1663           0 :                                 ++pBodyPtr;
    1664           0 :                                 if (--nLevel == 0)
    1665           0 :                                     goto comment_done;
    1666           0 :                                 break;
    1667             : 
    1668             :                             case '\\':
    1669           0 :                                 if (++pBodyPtr == pBodyEnd)
    1670           0 :                                     break;
    1671             :                             default:
    1672           0 :                                 aOutput << *pBodyPtr++;
    1673           0 :                                 break;
    1674             :                         }
    1675             :                 comment_done:
    1676           0 :                     break;
    1677             :                 }
    1678             : 
    1679             :                 case '<':
    1680             :                     // Write an already pending '<' if necessary:
    1681           0 :                     if (eBrackets == BRACKETS_OPENING)
    1682             :                     {
    1683           0 :                         if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1684           0 :                                 >= rSink.getLineLengthLimit())
    1685           0 :                             rSink << INetMIMEOutputSink::endl << ' ';
    1686           0 :                         else if (bInitialSpace)
    1687           0 :                             rSink << ' ';
    1688           0 :                         rSink << '<';
    1689           0 :                         bInitialSpace = false;
    1690             :                     }
    1691             : 
    1692             :                     // Remember this '<' as pending, and open a bracketed
    1693             :                     // block:
    1694           0 :                     eBrackets = BRACKETS_OPENING;
    1695           0 :                     ++pBodyPtr;
    1696           0 :                     break;
    1697             : 
    1698             :                 case '>':
    1699             :                     // Write a pending '<' if necessary:
    1700           0 :                     if (eBrackets == BRACKETS_OPENING)
    1701             :                     {
    1702           0 :                         if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1703           0 :                                 >= rSink.getLineLengthLimit())
    1704           0 :                             rSink << INetMIMEOutputSink::endl << ' ';
    1705           0 :                         else if (bInitialSpace)
    1706           0 :                             rSink << ' ';
    1707           0 :                         rSink << '<';
    1708           0 :                         bInitialSpace = false;
    1709             :                     }
    1710             : 
    1711             :                     // Write this '>', and close any bracketed block:
    1712           0 :                     if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1713           0 :                             >= rSink.getLineLengthLimit())
    1714           0 :                         rSink << INetMIMEOutputSink::endl << ' ';
    1715           0 :                     else if (bInitialSpace)
    1716           0 :                         rSink << ' ';
    1717           0 :                     rSink << '>';
    1718           0 :                     bInitialSpace = false;
    1719           0 :                     eBrackets = BRACKETS_OUTSIDE;
    1720           0 :                     ++pBodyPtr;
    1721           0 :                     break;
    1722             : 
    1723             :                 case ',':
    1724             :                 case ':':
    1725             :                 case ';':
    1726             :                 case '\\':
    1727             :                 case ']':
    1728             :                     // Write a pending '<' if necessary:
    1729           0 :                     if (eBrackets == BRACKETS_OPENING)
    1730             :                     {
    1731           0 :                         if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1732           0 :                                 >= rSink.getLineLengthLimit())
    1733           0 :                             rSink << INetMIMEOutputSink::endl << ' ';
    1734           0 :                         else if (bInitialSpace)
    1735           0 :                             rSink << ' ';
    1736           0 :                         rSink << '<';
    1737           0 :                         bInitialSpace = false;
    1738           0 :                         eBrackets = BRACKETS_INSIDE;
    1739             :                     }
    1740             : 
    1741             :                     // Write this specials:
    1742           0 :                     if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1743           0 :                             >= rSink.getLineLengthLimit())
    1744           0 :                         rSink << INetMIMEOutputSink::endl << ' ';
    1745           0 :                     else if (bInitialSpace)
    1746           0 :                         rSink << ' ';
    1747           0 :                     rSink << sal_Char(*pBodyPtr++);
    1748           0 :                     bInitialSpace = false;
    1749           0 :                     break;
    1750             : 
    1751             :                 case '\x0D': // CR
    1752             :                     // A <CRLF WSP> adds to accumulated space, a <CR> not
    1753             :                     // followed by <LF WSP> starts 'junk':
    1754           0 :                     if (startsWithLineFolding(pBodyPtr, pBodyEnd))
    1755             :                     {
    1756           0 :                         bInitialSpace = true;
    1757           0 :                         pBodyPtr += 3;
    1758           0 :                         break;
    1759             :                     }
    1760             :                 default:
    1761             :                 {
    1762             :                     // The next token is either one of <"." / "@" / atom /
    1763             :                     // quoted-string / domain-literal>, or it's 'junk'; if it
    1764             :                     // is not 'junk', it is either a 'phrase' (i.e., it may
    1765             :                     // contain encoded-words) or a 'non-phrase' (i.e., it may
    1766             :                     // not contain encoded-words):
    1767             :                     enum Entity { ENTITY_JUNK, ENTITY_NON_PHRASE,
    1768             :                                   ENTITY_PHRASE };
    1769           0 :                     Entity eEntity = ENTITY_JUNK;
    1770           0 :                     switch (*pBodyPtr)
    1771             :                     {
    1772             :                         case '.':
    1773             :                         case '@':
    1774             :                         case '[':
    1775             :                             // A token of <"." / "@" / domain-literal> always
    1776             :                             // starts a 'non-phrase':
    1777           0 :                             eEntity = ENTITY_NON_PHRASE;
    1778           0 :                             break;
    1779             : 
    1780             :                         default:
    1781           0 :                             if (rtl::isAscii(*pBodyPtr)
    1782           0 :                                 && !isAtomChar(*pBodyPtr))
    1783             :                             {
    1784           0 :                                 eEntity = ENTITY_JUNK;
    1785           0 :                                 break;
    1786             :                             }
    1787             :                         case '"':
    1788             :                             // A token of <atom / quoted-string> can either be
    1789             :                             // a 'phrase' or a 'non-phrase':
    1790           0 :                             switch (eType)
    1791             :                             {
    1792             :                                 case HEADER_FIELD_STRUCTURED:
    1793           0 :                                     eEntity = ENTITY_NON_PHRASE;
    1794           0 :                                     break;
    1795             : 
    1796             :                                 case HEADER_FIELD_PHRASE:
    1797           0 :                                     eEntity = ENTITY_PHRASE;
    1798           0 :                                     break;
    1799             : 
    1800             :                                 case HEADER_FIELD_MESSAGE_ID:
    1801             :                                     // A 'phrase' if and only if outside any
    1802             :                                     // bracketed block:
    1803             :                                     eEntity
    1804             :                                         = eBrackets == BRACKETS_OUTSIDE ?
    1805             :                                               ENTITY_PHRASE :
    1806           0 :                                               ENTITY_NON_PHRASE;
    1807           0 :                                     break;
    1808             : 
    1809             :                                 case HEADER_FIELD_ADDRESS:
    1810             :                                 {
    1811             :                                     // A 'non-phrase' if and only if, after
    1812             :                                     // skipping this token and any following
    1813             :                                     // <linear-white-space> and <comment>s,
    1814             :                                     // there is no token left, or the next
    1815             :                                     // token is any of <"." / "@" / ">" / ","
    1816             :                                     // / ";">, or the next token is <":"> and
    1817             :                                     // is within a bracketed block:
    1818           0 :                                     const sal_Unicode * pLookAhead = pBodyPtr;
    1819           0 :                                     if (*pLookAhead == '"')
    1820             :                                     {
    1821             :                                         pLookAhead
    1822             :                                             = skipQuotedString(pLookAhead,
    1823           0 :                                                                pBodyEnd);
    1824           0 :                                         if (pLookAhead == pBodyPtr)
    1825           0 :                                             pLookAhead = pBodyEnd;
    1826             :                                     }
    1827             :                                     else
    1828           0 :                                         while (pLookAhead != pBodyEnd
    1829           0 :                                                && (isAtomChar(*pLookAhead)
    1830           0 :                                                    || !rtl::isAscii(
    1831           0 :                                                            *pLookAhead)))
    1832           0 :                                             ++pLookAhead;
    1833           0 :                                     while (pLookAhead != pBodyEnd)
    1834           0 :                                         switch (*pLookAhead)
    1835             :                                         {
    1836             :                                             case '\t':
    1837             :                                             case ' ':
    1838           0 :                                                 ++pLookAhead;
    1839           0 :                                                 break;
    1840             : 
    1841             :                                             case '(':
    1842             :                                             {
    1843             :                                                 const sal_Unicode * pPast
    1844             :                                                     = skipComment(pLookAhead,
    1845           0 :                                                                   pBodyEnd);
    1846             :                                                 pLookAhead
    1847             :                                                     = pPast == pLookAhead ?
    1848           0 :                                                           pBodyEnd : pPast;
    1849           0 :                                                 break;
    1850             :                                             }
    1851             : 
    1852             :                                             case ',':
    1853             :                                             case '.':
    1854             :                                             case ';':
    1855             :                                             case '>':
    1856             :                                             case '@':
    1857           0 :                                                 eEntity = ENTITY_NON_PHRASE;
    1858           0 :                                                 goto entity_determined;
    1859             : 
    1860             :                                             case ':':
    1861             :                                                 eEntity
    1862             :                                                     = eBrackets
    1863             :                                                          == BRACKETS_OUTSIDE ?
    1864             :                                                           ENTITY_PHRASE :
    1865           0 :                                                           ENTITY_NON_PHRASE;
    1866           0 :                                                 goto entity_determined;
    1867             : 
    1868             :                                             case '\x0D': // CR
    1869           0 :                                                 if (startsWithLineFolding(
    1870             :                                                         pLookAhead, pBodyEnd))
    1871             :                                                 {
    1872           0 :                                                     pLookAhead += 3;
    1873           0 :                                                     break;
    1874             :                                                 }
    1875             :                                             default:
    1876           0 :                                                 eEntity = ENTITY_PHRASE;
    1877           0 :                                                 goto entity_determined;
    1878             :                                         }
    1879           0 :                                     eEntity = ENTITY_NON_PHRASE;
    1880             :                                 entity_determined:
    1881           0 :                                     break;
    1882             :                                 }
    1883             : 
    1884             :                                 case HEADER_FIELD_TEXT:
    1885             :                                     OSL_ASSERT(false);
    1886           0 :                                     break;
    1887             :                             }
    1888             : 
    1889             :                             // In a 'non-phrase', a non-US-ASCII character
    1890             :                             // cannot be part of an <atom>, but instead the
    1891             :                             // whole entity is 'junk' rather than 'non-
    1892             :                             // phrase':
    1893           0 :                             if (eEntity == ENTITY_NON_PHRASE
    1894           0 :                                 && !rtl::isAscii(*pBodyPtr))
    1895           0 :                                 eEntity = ENTITY_JUNK;
    1896           0 :                             break;
    1897             :                     }
    1898             : 
    1899           0 :                     switch (eEntity)
    1900             :                     {
    1901             :                         case ENTITY_JUNK:
    1902             :                         {
    1903             :                             // Write a pending '<' if necessary:
    1904           0 :                             if (eBrackets == BRACKETS_OPENING)
    1905             :                             {
    1906           0 :                                 if (rSink.getColumn()
    1907           0 :                                             + (bInitialSpace ? 1 : 0)
    1908           0 :                                         >= rSink.getLineLengthLimit())
    1909           0 :                                     rSink << INetMIMEOutputSink::endl << ' ';
    1910           0 :                                 else if (bInitialSpace)
    1911           0 :                                     rSink << ' ';
    1912           0 :                                 rSink << '<';
    1913           0 :                                 bInitialSpace = false;
    1914           0 :                                 eBrackets = BRACKETS_INSIDE;
    1915             :                             }
    1916             : 
    1917             :                             // Calculate the length of in- and output:
    1918           0 :                             const sal_Unicode * pStart = pBodyPtr;
    1919           0 :                             sal_Size nLength = 0;
    1920           0 :                             bool bModify = false;
    1921           0 :                             bool bEnd = false;
    1922           0 :                             while (pBodyPtr != pBodyEnd && !bEnd)
    1923           0 :                                 switch (*pBodyPtr)
    1924             :                                 {
    1925             :                                     case '\x0D': // CR
    1926           0 :                                         if (startsWithLineFolding(pBodyPtr,
    1927             :                                                                   pBodyEnd))
    1928           0 :                                             bEnd = true;
    1929           0 :                                         else if (startsWithLineBreak(
    1930             :                                                      pBodyPtr, pBodyEnd))
    1931             :                                         {
    1932           0 :                                             nLength += 3;
    1933           0 :                                             bModify = true;
    1934           0 :                                             pBodyPtr += 2;
    1935             :                                         }
    1936             :                                         else
    1937             :                                         {
    1938           0 :                                             ++nLength;
    1939           0 :                                             ++pBodyPtr;
    1940             :                                         }
    1941           0 :                                         break;
    1942             : 
    1943             :                                     case '\t':
    1944             :                                     case ' ':
    1945           0 :                                         bEnd = true;
    1946           0 :                                         break;
    1947             : 
    1948             :                                     default:
    1949           0 :                                         if (isVisible(*pBodyPtr))
    1950           0 :                                             bEnd = true;
    1951           0 :                                         else if (rtl::isAscii(*pBodyPtr))
    1952             :                                         {
    1953           0 :                                             ++nLength;
    1954           0 :                                             ++pBodyPtr;
    1955             :                                         }
    1956             :                                         else
    1957             :                                         {
    1958             :                                             nLength += getUTF8OctetCount(
    1959           0 :                                                            *pBodyPtr++);
    1960           0 :                                             bModify = true;
    1961             :                                         }
    1962           0 :                                         break;
    1963             :                                 }
    1964             : 
    1965             :                             // Write the output:
    1966           0 :                             if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    1967           0 :                                         + nLength
    1968           0 :                                     > rSink.getLineLengthLimit())
    1969           0 :                                 rSink << INetMIMEOutputSink::endl << ' ';
    1970           0 :                             else if (bInitialSpace)
    1971           0 :                                 rSink << ' ';
    1972           0 :                             bInitialSpace = false;
    1973           0 :                             if (bModify)
    1974           0 :                                 while (pStart != pBodyPtr)
    1975           0 :                                     if (startsWithLineBreak(pStart, pBodyPtr))
    1976             :                                     {
    1977           0 :                                         rSink << "\x0D\\\x0A"; // CR, '\', LF
    1978           0 :                                         pStart += 2;
    1979             :                                     }
    1980             :                                     else
    1981           0 :                                         writeUTF8(rSink, *pStart++);
    1982             :                             else
    1983           0 :                                 rSink.write(pStart, pBodyPtr);
    1984           0 :                             break;
    1985             :                         }
    1986             : 
    1987             :                         case ENTITY_NON_PHRASE:
    1988             :                         {
    1989             :                             // Calculate the length of in- and output:
    1990           0 :                             const sal_Unicode * pStart = pBodyPtr;
    1991           0 :                             sal_Size nLength = 0;
    1992           0 :                             bool bBracketedBlock = false;
    1993           0 :                             bool bSymbol = *pStart != '.' && *pStart != '@';
    1994           0 :                             bool bModify = false;
    1995           0 :                             bool bEnd = false;
    1996           0 :                             while (pBodyPtr != pBodyEnd && !bEnd)
    1997           0 :                                 switch (*pBodyPtr)
    1998             :                                 {
    1999             :                                     case '\t':
    2000             :                                     case ' ':
    2001             :                                     case '\x0D': // CR
    2002             :                                     {
    2003             :                                         const sal_Unicode * pLookAhead
    2004             :                                             = skipLinearWhiteSpace(pBodyPtr,
    2005           0 :                                                                    pBodyEnd);
    2006           0 :                                         if (pLookAhead < pBodyEnd
    2007           0 :                                             && (bSymbol ?
    2008           0 :                                                     isAtomChar(*pLookAhead)
    2009           0 :                                                     || *pLookAhead == '"'
    2010           0 :                                                     || *pLookAhead == '[' :
    2011           0 :                                                     *pLookAhead == '.'
    2012           0 :                                                     || *pLookAhead == '@'
    2013           0 :                                                     || (*pLookAhead == '>'
    2014           0 :                                                        && eType
    2015           0 :                                                     >= HEADER_FIELD_MESSAGE_ID
    2016           0 :                                                        && eBrackets
    2017             :                                                          == BRACKETS_OPENING)))
    2018             :                                         {
    2019           0 :                                             bModify = true;
    2020           0 :                                             pBodyPtr = pLookAhead;
    2021             :                                         }
    2022             :                                         else
    2023           0 :                                             bEnd = true;
    2024           0 :                                         break;
    2025             :                                     }
    2026             : 
    2027             :                                     case '"':
    2028           0 :                                         if (bSymbol)
    2029             :                                         {
    2030             :                                             pBodyPtr
    2031             :                                                 = scanQuotedBlock(pBodyPtr,
    2032             :                                                                   pBodyEnd,
    2033             :                                                                   '"', '"',
    2034             :                                                                   nLength,
    2035           0 :                                                                   bModify);
    2036           0 :                                             bSymbol = false;
    2037             :                                         }
    2038             :                                         else
    2039           0 :                                             bEnd = true;
    2040           0 :                                         break;
    2041             : 
    2042             :                                     case '[':
    2043           0 :                                         if (bSymbol)
    2044             :                                         {
    2045             :                                             pBodyPtr
    2046             :                                                 = scanQuotedBlock(pBodyPtr,
    2047             :                                                                   pBodyEnd,
    2048             :                                                                   '[', ']',
    2049             :                                                                   nLength,
    2050           0 :                                                                   bModify);
    2051           0 :                                             bSymbol = false;
    2052             :                                         }
    2053             :                                         else
    2054           0 :                                             bEnd = true;
    2055           0 :                                         break;
    2056             : 
    2057             :                                     case '.':
    2058             :                                     case '@':
    2059           0 :                                         if (bSymbol)
    2060           0 :                                             bEnd = true;
    2061             :                                         else
    2062             :                                         {
    2063           0 :                                             ++nLength;
    2064           0 :                                             bSymbol = true;
    2065           0 :                                             ++pBodyPtr;
    2066             :                                         }
    2067           0 :                                         break;
    2068             : 
    2069             :                                     case '>':
    2070           0 :                                         if (eBrackets == BRACKETS_OPENING
    2071           0 :                                             && eType
    2072           0 :                                                    >= HEADER_FIELD_MESSAGE_ID)
    2073             :                                         {
    2074           0 :                                             ++nLength;
    2075           0 :                                             bBracketedBlock = true;
    2076           0 :                                             ++pBodyPtr;
    2077             :                                         }
    2078           0 :                                         bEnd = true;
    2079           0 :                                         break;
    2080             : 
    2081             :                                     default:
    2082           0 :                                         if (isAtomChar(*pBodyPtr) && bSymbol)
    2083             :                                         {
    2084           0 :                                             while (pBodyPtr != pBodyEnd
    2085           0 :                                                    && isAtomChar(*pBodyPtr))
    2086             :                                             {
    2087           0 :                                                 ++nLength;
    2088           0 :                                                 ++pBodyPtr;
    2089             :                                             }
    2090           0 :                                             bSymbol = false;
    2091             :                                         }
    2092             :                                         else
    2093             :                                         {
    2094           0 :                                             if (!rtl::isAscii(*pBodyPtr))
    2095           0 :                                                 bModify = true;
    2096           0 :                                             bEnd = true;
    2097             :                                         }
    2098           0 :                                         break;
    2099             :                                 }
    2100             : 
    2101             :                             // Write a pending '<' if necessary:
    2102           0 :                             if (eBrackets == BRACKETS_OPENING
    2103           0 :                                 && !bBracketedBlock)
    2104             :                             {
    2105           0 :                                 if (rSink.getColumn()
    2106           0 :                                             + (bInitialSpace ? 1 : 0)
    2107           0 :                                         >= rSink.getLineLengthLimit())
    2108           0 :                                     rSink << INetMIMEOutputSink::endl << ' ';
    2109           0 :                                 else if (bInitialSpace)
    2110           0 :                                     rSink << ' ';
    2111           0 :                                 rSink << '<';
    2112           0 :                                 bInitialSpace = false;
    2113           0 :                                 eBrackets = BRACKETS_INSIDE;
    2114             :                             }
    2115             : 
    2116             :                             // Write the output:
    2117           0 :                             if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
    2118           0 :                                         + nLength
    2119           0 :                                     > rSink.getLineLengthLimit())
    2120           0 :                                 rSink << INetMIMEOutputSink::endl << ' ';
    2121           0 :                             else if (bInitialSpace)
    2122           0 :                                 rSink << ' ';
    2123           0 :                             bInitialSpace = false;
    2124           0 :                             if (bBracketedBlock)
    2125             :                             {
    2126           0 :                                 rSink << '<';
    2127           0 :                                 eBrackets = BRACKETS_OUTSIDE;
    2128             :                             }
    2129           0 :                             if (bModify)
    2130             :                             {
    2131             :                                 enum Mode { MODE_PLAIN, MODE_QUOTED_STRING,
    2132             :                                             MODE_DOMAIN_LITERAL };
    2133           0 :                                 Mode eMode = MODE_PLAIN;
    2134           0 :                                 while (pStart != pBodyPtr)
    2135           0 :                                     switch (*pStart)
    2136             :                                     {
    2137             :                                         case '\x0D': // CR
    2138           0 :                                             if (startsWithLineFolding(
    2139             :                                                     pStart, pBodyPtr))
    2140             :                                             {
    2141           0 :                                                 if (eMode != MODE_PLAIN)
    2142             :                                                     rSink << sal_Char(
    2143           0 :                                                                  pStart[2]);
    2144           0 :                                                 pStart += 3;
    2145             :                                             }
    2146           0 :                                             else if (startsWithLineBreak(
    2147             :                                                          pStart, pBodyPtr))
    2148             :                                             {
    2149           0 :                                                 rSink << "\x0D\\\x0A";
    2150             :                                                     // CR, '\', LF
    2151           0 :                                                 pStart += 2;
    2152             :                                             }
    2153             :                                             else
    2154             :                                             {
    2155           0 :                                                 rSink << '\x0D'; // CR
    2156           0 :                                                 ++pStart;
    2157             :                                             }
    2158           0 :                                             break;
    2159             : 
    2160             :                                         case '\t':
    2161             :                                         case ' ':
    2162           0 :                                             if (eMode != MODE_PLAIN)
    2163           0 :                                                 rSink << sal_Char(*pStart);
    2164           0 :                                             ++pStart;
    2165           0 :                                             break;
    2166             : 
    2167             :                                         case '"':
    2168           0 :                                             if (eMode == MODE_PLAIN)
    2169           0 :                                                 eMode = MODE_QUOTED_STRING;
    2170           0 :                                             else if (eMode
    2171             :                                                         == MODE_QUOTED_STRING)
    2172           0 :                                                 eMode = MODE_PLAIN;
    2173           0 :                                             rSink << '"';
    2174           0 :                                             ++pStart;
    2175           0 :                                             break;
    2176             : 
    2177             :                                         case '[':
    2178           0 :                                             if (eMode == MODE_PLAIN)
    2179           0 :                                                 eMode = MODE_DOMAIN_LITERAL;
    2180           0 :                                             rSink << '[';
    2181           0 :                                             ++pStart;
    2182           0 :                                             break;
    2183             : 
    2184             :                                         case ']':
    2185           0 :                                             if (eMode == MODE_DOMAIN_LITERAL)
    2186           0 :                                                 eMode = MODE_PLAIN;
    2187           0 :                                             rSink << ']';
    2188           0 :                                             ++pStart;
    2189           0 :                                             break;
    2190             : 
    2191             :                                         case '\\':
    2192           0 :                                             rSink << '\\';
    2193           0 :                                             if (++pStart < pBodyPtr)
    2194           0 :                                                 writeUTF8(rSink, *pStart++);
    2195           0 :                                             break;
    2196             : 
    2197             :                                         default:
    2198           0 :                                             writeUTF8(rSink, *pStart++);
    2199           0 :                                             break;
    2200             :                                     }
    2201             :                             }
    2202             :                             else
    2203           0 :                                 rSink.write(pStart, pBodyPtr);
    2204           0 :                             break;
    2205             :                         }
    2206             : 
    2207             :                         case ENTITY_PHRASE:
    2208             :                         {
    2209             :                             // Write a pending '<' if necessary:
    2210           0 :                             if (eBrackets == BRACKETS_OPENING)
    2211             :                             {
    2212           0 :                                 if (rSink.getColumn()
    2213           0 :                                             + (bInitialSpace ? 1 : 0)
    2214           0 :                                         >= rSink.getLineLengthLimit())
    2215           0 :                                     rSink << INetMIMEOutputSink::endl << ' ';
    2216           0 :                                 else if (bInitialSpace)
    2217           0 :                                     rSink << ' ';
    2218           0 :                                 rSink << '<';
    2219           0 :                                 bInitialSpace = false;
    2220           0 :                                 eBrackets = BRACKETS_INSIDE;
    2221             :                             }
    2222             : 
    2223             :                             // Calculate the length of in- and output:
    2224           0 :                             const sal_Unicode * pStart = pBodyPtr;
    2225           0 :                             bool bQuotedString = false;
    2226           0 :                             bool bEnd = false;
    2227           0 :                             while (pBodyPtr != pBodyEnd && !bEnd)
    2228           0 :                                 switch (*pBodyPtr)
    2229             :                                 {
    2230             :                                     case '\t':
    2231             :                                     case ' ':
    2232             :                                     case '\x0D': // CR
    2233           0 :                                         if (bQuotedString)
    2234           0 :                                             ++pBodyPtr;
    2235             :                                         else
    2236             :                                         {
    2237             :                                             const sal_Unicode * pLookAhead
    2238             :                                                 = skipLinearWhiteSpace(
    2239           0 :                                                       pBodyPtr, pBodyEnd);
    2240           0 :                                             if (pLookAhead != pBodyEnd
    2241           0 :                                                 && (isAtomChar(*pLookAhead)
    2242           0 :                                                     || !rtl::isAscii(*pLookAhead)
    2243           0 :                                                     || *pLookAhead == '"'))
    2244           0 :                                                 pBodyPtr = pLookAhead;
    2245             :                                             else
    2246           0 :                                                 bEnd = true;
    2247             :                                         }
    2248           0 :                                         break;
    2249             : 
    2250             :                                     case '"':
    2251           0 :                                         bQuotedString = !bQuotedString;
    2252           0 :                                         ++pBodyPtr;
    2253           0 :                                         break;
    2254             : 
    2255             :                                     case '\\':
    2256           0 :                                         if (bQuotedString)
    2257             :                                         {
    2258           0 :                                             if (++pBodyPtr != pBodyEnd)
    2259           0 :                                                 ++pBodyPtr;
    2260             :                                         }
    2261             :                                         else
    2262           0 :                                             bEnd = true;
    2263           0 :                                         break;
    2264             : 
    2265             :                                     default:
    2266           0 :                                         if (bQuotedString
    2267           0 :                                             || isAtomChar(*pBodyPtr)
    2268           0 :                                             || !rtl::isAscii(*pBodyPtr))
    2269           0 :                                             ++pBodyPtr;
    2270             :                                         else
    2271           0 :                                             bEnd = true;
    2272           0 :                                         break;
    2273             :                                 }
    2274             : 
    2275             :                             // Write the phrase, introducing encoded-words
    2276             :                             // where necessary:
    2277             :                             INetMIMEEncodedWordOutputSink
    2278             :                                 aOutput(
    2279             :                                     rSink,
    2280             :                                 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,
    2281             :                                     bInitialSpace ?
    2282             :                                  INetMIMEEncodedWordOutputSink::SPACE_ALWAYS :
    2283             :                                  INetMIMEEncodedWordOutputSink::SPACE_ENCODED,
    2284           0 :                                ePreferredEncoding);
    2285           0 :                             while (pStart != pBodyPtr)
    2286           0 :                                 switch (*pStart)
    2287             :                                 {
    2288             :                                     case '"':
    2289           0 :                                         ++pStart;
    2290           0 :                                         break;
    2291             : 
    2292             :                                     case '\\':
    2293           0 :                                         if (++pStart != pBodyPtr)
    2294           0 :                                             aOutput << *pStart++;
    2295           0 :                                         break;
    2296             : 
    2297             :                                     case '\x0D': // CR
    2298           0 :                                         pStart += 2;
    2299           0 :                                         aOutput << *pStart++;
    2300           0 :                                         break;
    2301             : 
    2302             :                                     default:
    2303           0 :                                         aOutput << *pStart++;
    2304           0 :                                         break;
    2305             :                                 }
    2306           0 :                             bInitialSpace = aOutput.flush();
    2307           0 :                             break;
    2308             :                         }
    2309             :                     }
    2310           0 :                     break;
    2311             :                 }
    2312             :             }
    2313             :     }
    2314           0 : }
    2315             : 
    2316             : // static
    2317           0 : bool INetMIME::translateUTF8Char(const sal_Char *& rBegin,
    2318             :                                  const sal_Char * pEnd,
    2319             :                                  rtl_TextEncoding eEncoding,
    2320             :                                  sal_uInt32 & rCharacter)
    2321             : {
    2322           0 :     if (rBegin == pEnd || static_cast< unsigned char >(*rBegin) < 0x80
    2323           0 :         || static_cast< unsigned char >(*rBegin) >= 0xFE)
    2324           0 :         return false;
    2325             : 
    2326             :     int nCount;
    2327             :     sal_uInt32 nMin;
    2328             :     sal_uInt32 nUCS4;
    2329           0 :     const sal_Char * p = rBegin;
    2330           0 :     if (static_cast< unsigned char >(*p) < 0xE0)
    2331             :     {
    2332           0 :         nCount = 1;
    2333           0 :         nMin = 0x80;
    2334           0 :         nUCS4 = static_cast< unsigned char >(*p) & 0x1F;
    2335             :     }
    2336           0 :     else if (static_cast< unsigned char >(*p) < 0xF0)
    2337             :     {
    2338           0 :         nCount = 2;
    2339           0 :         nMin = 0x800;
    2340           0 :         nUCS4 = static_cast< unsigned char >(*p) & 0xF;
    2341             :     }
    2342           0 :     else if (static_cast< unsigned char >(*p) < 0xF8)
    2343             :     {
    2344           0 :         nCount = 3;
    2345           0 :         nMin = 0x10000;
    2346           0 :         nUCS4 = static_cast< unsigned char >(*p) & 7;
    2347             :     }
    2348           0 :     else if (static_cast< unsigned char >(*p) < 0xFC)
    2349             :     {
    2350           0 :         nCount = 4;
    2351           0 :         nMin = 0x200000;
    2352           0 :         nUCS4 = static_cast< unsigned char >(*p) & 3;
    2353             :     }
    2354             :     else
    2355             :     {
    2356           0 :         nCount = 5;
    2357           0 :         nMin = 0x4000000;
    2358           0 :         nUCS4 = static_cast< unsigned char >(*p) & 1;
    2359             :     }
    2360           0 :     ++p;
    2361             : 
    2362           0 :     for (; nCount-- > 0; ++p)
    2363           0 :         if ((static_cast< unsigned char >(*p) & 0xC0) == 0x80)
    2364           0 :             nUCS4 = (nUCS4 << 6) | (static_cast< unsigned char >(*p) & 0x3F);
    2365             :         else
    2366           0 :             return false;
    2367             : 
    2368           0 :     if (nUCS4 < nMin || nUCS4 > 0x10FFFF)
    2369           0 :         return false;
    2370             : 
    2371           0 :     if (eEncoding >= RTL_TEXTENCODING_UCS4)
    2372           0 :         rCharacter = nUCS4;
    2373             :     else
    2374             :     {
    2375             :         sal_Unicode aUTF16[2];
    2376           0 :         const sal_Unicode * pUTF16End = putUTF32Character(aUTF16, nUCS4);
    2377             :         sal_Size nSize;
    2378             :         sal_Char * pBuffer = convertFromUnicode(aUTF16, pUTF16End, eEncoding,
    2379           0 :                                                 nSize);
    2380           0 :         if (!pBuffer)
    2381           0 :             return false;
    2382             :         DBG_ASSERT(nSize == 1,
    2383             :                    "INetMIME::translateUTF8Char(): Bad conversion");
    2384           0 :         rCharacter = *pBuffer;
    2385           0 :         delete[] pBuffer;
    2386             :     }
    2387           0 :     rBegin = p;
    2388           0 :     return true;
    2389             : }
    2390             : 
    2391             : // static
    2392           0 : OUString INetMIME::decodeHeaderFieldBody(HeaderFieldType eType,
    2393             :                                           const OString& rBody)
    2394             : {
    2395             :     // Due to a bug in INetCoreRFC822MessageStream::ConvertTo7Bit(), old
    2396             :     // versions of StarOffice send mails with header fields where encoded
    2397             :     // words can be preceded by '=', ',', '.', '"', or '(', and followed by
    2398             :     // '=', ',', '.', '"', ')', without any required white space in between.
    2399             :     // And there appear to exist some broken mailers that only encode single
    2400             :     // letters within words, like "Appel
    2401             :     // =?iso-8859-1?Q?=E0?=t=?iso-8859-1?Q?=E9?=moin", so it seems best to
    2402             :     // detect encoded words even when not propperly surrounded by white space.
    2403             : 
    2404             :     // Non US-ASCII characters in rBody are treated as ISO-8859-1.
    2405             : 
    2406             :     // encoded-word = "=?"
    2407             :     //     1*(%x21 / %x23-27 / %x2A-2B / %x2D / %30-39 / %x41-5A / %x5E-7E)
    2408             :     //     ["*" 1*8ALPHA *("-" 1*8ALPHA)] "?"
    2409             :     //     ("B?" *(4base64) (4base64 / 3base64 "=" / 2base64 "==")
    2410             :     //      / "Q?" 1*(%x21-3C / %x3E / %x40-7E / "=" 2HEXDIG))
    2411             :     //     "?="
    2412             : 
    2413             :     // base64 = ALPHA / DIGIT / "+" / "/"
    2414             : 
    2415           0 :     const sal_Char * pBegin = rBody.getStr();
    2416           0 :     const sal_Char * pEnd = pBegin + rBody.getLength();
    2417             : 
    2418           0 :     OUString sDecoded;
    2419           0 :     const sal_Char * pCopyBegin = pBegin;
    2420             : 
    2421             :     /* bool bStartEncodedWord = true; */
    2422           0 :     const sal_Char * pWSPBegin = pBegin;
    2423           0 :     bool bQuotedEncodedText = false;
    2424           0 :     sal_uInt32 nCommentLevel = 0;
    2425             : 
    2426           0 :     for (const sal_Char * p = pBegin; p != pEnd;)
    2427             :     {
    2428           0 :         OUString sEncodedText;
    2429           0 :         if (p != pEnd && *p == '=' /* && bStartEncodedWord */)
    2430             :         {
    2431           0 :             const sal_Char * q = p + 1;
    2432           0 :             bool bEncodedWord = q != pEnd && *q++ == '?';
    2433             : 
    2434           0 :             rtl_TextEncoding eCharsetEncoding = RTL_TEXTENCODING_DONTKNOW;
    2435           0 :             if (bEncodedWord)
    2436             :             {
    2437           0 :                 const sal_Char * pCharsetBegin = q;
    2438           0 :                 const sal_Char * pLanguageBegin = 0;
    2439           0 :                 int nAlphaCount = 0;
    2440           0 :                 for (bool bDone = false; !bDone;)
    2441           0 :                     if (q == pEnd)
    2442             :                     {
    2443           0 :                         bEncodedWord = false;
    2444           0 :                         bDone = true;
    2445             :                     }
    2446             :                     else
    2447             :                     {
    2448           0 :                         sal_Char cChar = *q++;
    2449           0 :                         switch (cChar)
    2450             :                         {
    2451             :                             case '*':
    2452           0 :                                 pLanguageBegin = q - 1;
    2453           0 :                                 nAlphaCount = 0;
    2454           0 :                                 break;
    2455             : 
    2456             :                             case '-':
    2457           0 :                                 if (pLanguageBegin != 0)
    2458             :                                 {
    2459           0 :                                     if (nAlphaCount == 0)
    2460           0 :                                         pLanguageBegin = 0;
    2461             :                                     else
    2462           0 :                                         nAlphaCount = 0;
    2463             :                                 }
    2464           0 :                                 break;
    2465             : 
    2466             :                             case '?':
    2467           0 :                                 if (pCharsetBegin == q - 1)
    2468           0 :                                     bEncodedWord = false;
    2469             :                                 else
    2470             :                                 {
    2471             :                                     eCharsetEncoding
    2472             :                                         = getCharsetEncoding(
    2473             :                                               pCharsetBegin,
    2474             :                                               pLanguageBegin == 0
    2475           0 :                                               || nAlphaCount == 0 ?
    2476           0 :                                                   q - 1 : pLanguageBegin);
    2477             :                                     bEncodedWord = isMIMECharsetEncoding(
    2478           0 :                                                        eCharsetEncoding);
    2479             :                                     eCharsetEncoding
    2480           0 :                                         = translateFromMIME(eCharsetEncoding);
    2481             :                                 }
    2482           0 :                                 bDone = true;
    2483           0 :                                 break;
    2484             : 
    2485             :                             default:
    2486           0 :                                 if (pLanguageBegin != 0
    2487           0 :                                     && (!rtl::isAsciiAlpha(cChar) || ++nAlphaCount > 8))
    2488           0 :                                     pLanguageBegin = 0;
    2489           0 :                                 break;
    2490             :                         }
    2491             :                     }
    2492             :             }
    2493             : 
    2494           0 :             bool bEncodingB = false;
    2495           0 :             if (bEncodedWord)
    2496             :             {
    2497           0 :                 if (q == pEnd)
    2498           0 :                     bEncodedWord = false;
    2499             :                 else
    2500             :                 {
    2501           0 :                     switch (*q++)
    2502             :                     {
    2503             :                         case 'B':
    2504             :                         case 'b':
    2505           0 :                             bEncodingB = true;
    2506           0 :                             break;
    2507             : 
    2508             :                         case 'Q':
    2509             :                         case 'q':
    2510           0 :                             bEncodingB = false;
    2511           0 :                             break;
    2512             : 
    2513             :                         default:
    2514           0 :                             bEncodedWord = false;
    2515           0 :                             break;
    2516             :                     }
    2517             :                 }
    2518             :             }
    2519             : 
    2520           0 :             bEncodedWord = bEncodedWord && q != pEnd && *q++ == '?';
    2521             : 
    2522           0 :             OStringBuffer sText;
    2523           0 :             if (bEncodedWord)
    2524             :             {
    2525           0 :                 if (bEncodingB)
    2526             :                 {
    2527           0 :                     for (bool bDone = false; !bDone;)
    2528             :                     {
    2529           0 :                         if (pEnd - q < 4)
    2530             :                         {
    2531           0 :                             bEncodedWord = false;
    2532           0 :                             bDone = true;
    2533             :                         }
    2534             :                         else
    2535             :                         {
    2536           0 :                             bool bFinal = false;
    2537           0 :                             int nCount = 3;
    2538           0 :                             sal_uInt32 nValue = 0;
    2539           0 :                             for (int nShift = 18; nShift >= 0; nShift -= 6)
    2540             :                             {
    2541           0 :                                 int nWeight = getBase64Weight(*q++);
    2542           0 :                                 if (nWeight == -2)
    2543             :                                 {
    2544           0 :                                     bEncodedWord = false;
    2545           0 :                                     bDone = true;
    2546           0 :                                     break;
    2547             :                                 }
    2548           0 :                                 if (nWeight == -1)
    2549             :                                 {
    2550           0 :                                     if (!bFinal)
    2551             :                                     {
    2552           0 :                                         if (nShift >= 12)
    2553             :                                         {
    2554           0 :                                             bEncodedWord = false;
    2555           0 :                                             bDone = true;
    2556           0 :                                             break;
    2557             :                                         }
    2558           0 :                                         bFinal = true;
    2559           0 :                                         nCount = nShift == 6 ? 1 : 2;
    2560             :                                     }
    2561             :                                 }
    2562             :                                 else
    2563           0 :                                     nValue |= nWeight << nShift;
    2564             :                             }
    2565           0 :                             if (bEncodedWord)
    2566             :                             {
    2567           0 :                                 for (int nShift = 16; nCount-- > 0; nShift -= 8)
    2568           0 :                                     sText.append(sal_Char(nValue >> nShift & 0xFF));
    2569           0 :                                 if (*q == '?')
    2570             :                                 {
    2571           0 :                                     ++q;
    2572           0 :                                     bDone = true;
    2573             :                                 }
    2574           0 :                                 if (bFinal && !bDone)
    2575             :                                 {
    2576           0 :                                     bEncodedWord = false;
    2577           0 :                                     bDone = true;
    2578             :                                 }
    2579             :                             }
    2580             :                         }
    2581             :                     }
    2582             :                 }
    2583             :                 else
    2584             :                 {
    2585           0 :                     const sal_Char * pEncodedTextBegin = q;
    2586           0 :                     const sal_Char * pEncodedTextCopyBegin = q;
    2587           0 :                     for (bool bDone = false; !bDone;)
    2588           0 :                         if (q == pEnd)
    2589             :                         {
    2590           0 :                             bEncodedWord = false;
    2591           0 :                             bDone = true;
    2592             :                         }
    2593             :                         else
    2594             :                         {
    2595           0 :                             sal_uInt32 nChar = *q++;
    2596           0 :                             switch (nChar)
    2597             :                             {
    2598             :                                 case '=':
    2599             :                                 {
    2600           0 :                                     if (pEnd - q < 2)
    2601             :                                     {
    2602           0 :                                         bEncodedWord = false;
    2603           0 :                                         bDone = true;
    2604           0 :                                         break;
    2605             :                                     }
    2606           0 :                                     int nDigit1 = getHexWeight(q[0]);
    2607           0 :                                     int nDigit2 = getHexWeight(q[1]);
    2608           0 :                                     if (nDigit1 < 0 || nDigit2 < 0)
    2609             :                                     {
    2610           0 :                                         bEncodedWord = false;
    2611           0 :                                         bDone = true;
    2612           0 :                                         break;
    2613             :                                     }
    2614             :                                     sText.append(rBody.copy(
    2615           0 :                                         (pEncodedTextCopyBegin - pBegin),
    2616           0 :                                         (q - 1 - pEncodedTextCopyBegin)));
    2617           0 :                                     sText.append(sal_Char(nDigit1 << 4 | nDigit2));
    2618           0 :                                     q += 2;
    2619           0 :                                     pEncodedTextCopyBegin = q;
    2620           0 :                                     break;
    2621             :                                 }
    2622             : 
    2623             :                                 case '?':
    2624           0 :                                     if (q - pEncodedTextBegin > 1)
    2625             :                                         sText.append(rBody.copy(
    2626           0 :                                             (pEncodedTextCopyBegin - pBegin),
    2627           0 :                                             (q - 1 - pEncodedTextCopyBegin)));
    2628             :                                     else
    2629           0 :                                         bEncodedWord = false;
    2630           0 :                                     bDone = true;
    2631           0 :                                     break;
    2632             : 
    2633             :                                 case '_':
    2634             :                                     sText.append(rBody.copy(
    2635           0 :                                         (pEncodedTextCopyBegin - pBegin),
    2636           0 :                                         (q - 1 - pEncodedTextCopyBegin)));
    2637           0 :                                     sText.append(' ');
    2638           0 :                                     pEncodedTextCopyBegin = q;
    2639           0 :                                     break;
    2640             : 
    2641             :                                 default:
    2642           0 :                                     if (!isVisible(nChar))
    2643             :                                     {
    2644           0 :                                         bEncodedWord = false;
    2645           0 :                                         bDone = true;
    2646             :                                     }
    2647           0 :                                     break;
    2648             :                             }
    2649             :                         }
    2650             :                 }
    2651             :             }
    2652             : 
    2653           0 :             bEncodedWord = bEncodedWord && q != pEnd && *q++ == '=';
    2654             : 
    2655           0 :             sal_Unicode * pUnicodeBuffer = 0;
    2656           0 :             sal_Size nUnicodeSize = 0;
    2657           0 :             if (bEncodedWord)
    2658             :             {
    2659             :                 pUnicodeBuffer
    2660             :                     = convertToUnicode(sText.getStr(),
    2661           0 :                                        sText.getStr() + sText.getLength(),
    2662           0 :                                        eCharsetEncoding, nUnicodeSize);
    2663           0 :                 if (pUnicodeBuffer == 0)
    2664           0 :                     bEncodedWord = false;
    2665             :             }
    2666             : 
    2667           0 :             if (bEncodedWord)
    2668             :             {
    2669           0 :                 appendISO88591(sDecoded, pCopyBegin, pWSPBegin);
    2670           0 :                 if (eType == HEADER_FIELD_TEXT)
    2671           0 :                     sDecoded += OUString(
    2672             :                         pUnicodeBuffer,
    2673           0 :                         static_cast< sal_Int32 >(nUnicodeSize));
    2674           0 :                 else if (nCommentLevel == 0)
    2675             :                 {
    2676           0 :                     sEncodedText = OUString(pUnicodeBuffer, nUnicodeSize);
    2677           0 :                     if (!bQuotedEncodedText)
    2678             :                     {
    2679           0 :                         const sal_Unicode * pTextPtr = pUnicodeBuffer;
    2680             :                         const sal_Unicode * pTextEnd = pTextPtr
    2681           0 :                                                            + nUnicodeSize;
    2682           0 :                         for (; pTextPtr != pTextEnd; ++pTextPtr)
    2683           0 :                             if (!isEncodedWordTokenChar(*pTextPtr))
    2684             :                             {
    2685           0 :                                 bQuotedEncodedText = true;
    2686           0 :                                 break;
    2687             :                             }
    2688             :                     }
    2689             :                 }
    2690             :                 else
    2691             :                 {
    2692           0 :                     const sal_Unicode * pTextPtr = pUnicodeBuffer;
    2693           0 :                     const sal_Unicode * pTextEnd = pTextPtr + nUnicodeSize;
    2694           0 :                     for (; pTextPtr != pTextEnd; ++pTextPtr)
    2695             :                     {
    2696           0 :                         switch (*pTextPtr)
    2697             :                         {
    2698             :                             case '(':
    2699             :                             case ')':
    2700             :                             case '\\':
    2701             :                             case '\x0D':
    2702             :                             case '=':
    2703           0 :                                 sDecoded += "\\";
    2704           0 :                                 break;
    2705             :                         }
    2706           0 :                         sDecoded += OUString(*pTextPtr);
    2707             :                     }
    2708             :                 }
    2709           0 :                 delete[] pUnicodeBuffer;
    2710           0 :                 p = q;
    2711           0 :                 pCopyBegin = p;
    2712             : 
    2713           0 :                 pWSPBegin = p;
    2714           0 :                 while (p != pEnd && isWhiteSpace(*p))
    2715           0 :                     ++p;
    2716             :                 /* bStartEncodedWord = p != pWSPBegin; */
    2717           0 :                 continue;
    2718           0 :             }
    2719             :         }
    2720             : 
    2721           0 :         if (!sEncodedText.isEmpty())
    2722             :         {
    2723           0 :             if (bQuotedEncodedText)
    2724             :             {
    2725           0 :                 sDecoded += "\"";
    2726           0 :                 const sal_Unicode * pTextPtr = sEncodedText.getStr();
    2727           0 :                 const sal_Unicode * pTextEnd = pTextPtr + sEncodedText.getLength();
    2728           0 :                 for (;pTextPtr != pTextEnd; ++pTextPtr)
    2729             :                 {
    2730           0 :                     switch (*pTextPtr)
    2731             :                     {
    2732             :                         case '"':
    2733             :                         case '\\':
    2734             :                         case '\x0D':
    2735           0 :                             sDecoded += "\\";
    2736           0 :                             break;
    2737             :                     }
    2738           0 :                     sDecoded += OUString(*pTextPtr);
    2739             :                 }
    2740           0 :                 sDecoded += "\"";
    2741             :             }
    2742             :             else
    2743           0 :                 sDecoded += sEncodedText;
    2744           0 :             bQuotedEncodedText = false;
    2745             :         }
    2746             : 
    2747           0 :         if (p == pEnd)
    2748           0 :             break;
    2749             : 
    2750           0 :         switch (*p++)
    2751             :         {
    2752             :             case '"':
    2753           0 :                 if (eType != HEADER_FIELD_TEXT && nCommentLevel == 0)
    2754             :                 {
    2755             :                     const sal_Char * pQuotedStringEnd
    2756           0 :                         = skipQuotedString(p - 1, pEnd);
    2757           0 :                     p = pQuotedStringEnd == p - 1 ? pEnd : pQuotedStringEnd;
    2758             :                 }
    2759             :                 /* bStartEncodedWord = true; */
    2760           0 :                 break;
    2761             : 
    2762             :             case '(':
    2763           0 :                 if (eType != HEADER_FIELD_TEXT)
    2764           0 :                     ++nCommentLevel;
    2765             :                 /* bStartEncodedWord = true; */
    2766           0 :                 break;
    2767             : 
    2768             :             case ')':
    2769           0 :                 if (nCommentLevel > 0)
    2770           0 :                     --nCommentLevel;
    2771             :                 /* bStartEncodedWord = false; */
    2772           0 :                 break;
    2773             : 
    2774             :             default:
    2775             :             {
    2776           0 :                 const sal_Char * pUTF8Begin = p - 1;
    2777           0 :                 const sal_Char * pUTF8End = pUTF8Begin;
    2778           0 :                 sal_uInt32 nCharacter = 0;
    2779           0 :                 if (translateUTF8Char(pUTF8End, pEnd, RTL_TEXTENCODING_UCS4,
    2780             :                                       nCharacter))
    2781             :                 {
    2782           0 :                     appendISO88591(sDecoded, pCopyBegin, p - 1);
    2783             :                     sal_Unicode aUTF16Buf[2];
    2784           0 :                     sal_Int32 nUTF16Len = 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           0 :     appendISO88591(sDecoded, pCopyBegin, pEnd);
    2797           0 :     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 !rtl::isAscii(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(static_cast<unsigned char>(
    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 = static_cast<unsigned char>(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 = !rtl::isAscii(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           0 : void INetContentTypeParameterList::Clear()
    3731             : {
    3732           0 :     maEntries.clear();
    3733           0 : }
    3734             : 
    3735             : const INetContentTypeParameter *
    3736           0 : INetContentTypeParameterList::find(const OString& rAttribute) const
    3737             : {
    3738           0 :     boost::ptr_vector<INetContentTypeParameter>::const_iterator iter;
    3739           0 :     for (iter = maEntries.begin(); iter != maEntries.end(); ++iter)
    3740             :     {
    3741           0 :         if (iter->m_sAttribute.equalsIgnoreAsciiCase(rAttribute))
    3742           0 :             return &(*iter);
    3743             :     }
    3744             : 
    3745           0 :     return NULL;
    3746             : }
    3747             : 
    3748             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10