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

Generated by: LCOV version 1.11